LoginSignup
77

More than 3 years have passed since last update.

DockerイメージをECRからプライベートな接続で取得するにはPrivate Linkを使うべし

Last updated at Posted at 2019-04-05

image.png

【問題】
プライベートサブネットのインスタンスがECRからDockerイメージをプライベート接続でpullしたい。
インターネットゲートウェイ、NATゲートウェイを使用せずに外部接続無しで実現するにはどのようにするか。

image.png

【答え】
2019年1月のAWS Private linkのサポートによりこの問題は解決された。

その方法を投稿する。

image.png

AWS Private Linkとは

AWSサービスへのアクセスをプライベートに接続できる高可用性、高スケールラブルなNWサービス。

Private Link Endpointを設定するとVPC内でプライベートIP付きのENIが作成される。

AWS PrivateLinkサポートにより、パブリック or プライベート 関わらずインスタンスはECRからプライベートな接続でイメージをダウンロードすることができる。

もちろん、NATゲートウェイやインターネットゲートウェイは必要ない。

不必要なアウトバウンド向け通信をブロックしたい時などのにも使用でき、セキュリティ強化となる。

Fargate使用においても、タスクにパブリックIPをアサインすることなくDocker imageをpullできる。

今回、AWS PrivateLinkの作成は複数に渡る。

1.AWS PrivateLink endpoints for ECR.

インスタンスはECRと接続でき、Docker manifestファイルをダウンロードできる。

2.Gateway VPC endpoint for Amazon S3.

インスタンスはプライベートなS3バケットに接続でき、そこに配置されたDocker レイヤーファイルをダウンロードできる


 ※Docker imageはManifestファイル(JSON形式)とレイヤーファイル(tar.gz形式)から構成される
  以降、Docker imageファイル、Docker manifestファイル、Docker レイヤーファイルと記述する
  Docker imageファイル = (Docker manifestファイル + Docker レイヤーファイル)


3.AWS PrivateLink endpoints for ECS.

インスタンスはECS用のVPCエンドポイントの作成時に使用する3つのドメイン(telemetryとecsコントロールプレーンのagentサービス)と接続可能となる。

  • com.amazonaws.region.ecs-agent
  • com.amazonaws.region.ecs-telemetry
  • com.amazonaws.region.ecs

ECR接続用のPrivateLink endpointを作成する

image.png

ECRとの接続は2つのエンドポイントが必要

  •  com.amazonaws.region.ecr.api
  •  com.amazonaws.region.ecr.dkr

region は使用リージョンに置き換える。(ap-northeast-1 など)

VPCのマネジメントコンソール左メニューよりエンドポイントを作成する。

image.png

次に、PrivateLinkを配置するVPCとサブネットを決める。
ECSクラスターを実行するVPCと同じ場所に配置することを確認すること。
大規模障害を考慮し、リスト表示される全てのAZとサブネットを選択する。

ただし、ネットワークのニーズに応じて、各アベイラビリティーゾーンのプライベートサブネットでのみ
AWS PrivateLinkエンドポイントを有効にすることできる。

image.png

次に、Enable Private DNS Nameを有効にする。

image.png

Route53などで設定したプライベートホストゾーンを設定している方は、ECRのデフォルトのドメイン(https://api.ecr.region.amazonaws.com) を使用してリソースにアクセス可能。

エンドポイントのプライベートホストネームや、プライベートIPv4アドレスを使用する必要は無く、自動的に名前解決してアクセスできる。

プライベートホストゾーンを設定している、かつ2019年1月24日以降にリリースされたSDKを使用する場合のコマンド例

aws ecr describe-repositories

プライベートホストゾーンを設定していない場合のコマンド例

aws --endpoint-url https://VPC_Endpoint_ID.api.ecr.region.vpce.amazonaws.com ecr describe-repositories

プライベートホストゾーンで com.amazonaws.region.ecr.api を設定している、かつ2019年1月24日以前にリリースされたSDK、もしくはaws cliコマンドを使用する場合はエンドポイントを特定すること。

aws --endpoint-url https://api.ecr.region.amazonaws.com

image.png

最後に、エンドポイント自体にセキュリティーグループを設定する。

セキュリティーグループはエンドポイントに接続するプライベートサブネットのインバウンド通信(ポート443)を許可すること。

もしくはクラスターのオートスケーリンググループに対して許可する場合もあるし、全てのインスタンスからの接続を許可することもできる。

Create Endpointを選択する。作成したエンドポイントが表示される。

Gateway VPC endpoint for Amazon S3を作成する

image.png

次はGateway VPC endpoint for Amazon S3を作成する。

え?なぜS3へのアクセスが必要なのか?

それはECRはDockerレイヤーファイルをS3に保管するから。

インスタンスがECRからDokcer manifestファイルを取得し、S3から(イメージの実体である)Docker レイヤーファイルをダウンロードする。

ちなみに、Docker レイヤーファイルの保管ARNは以下

arn:aws:s3:::prod-region-starport-layer-bucket/*

ECRを使用するにあたり、S3に対して設定する最小限のアクセスは以下

{
  "Statement": [
    {
      "Sid": "Access-to-specific-bucket-only",
      "Principal": "*",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::prod-region-starport-layer-bucket/*"]
    }
  ]
}

S3はゲートウェイと呼ばれる少々違ったタイプのエンドポイントを使用する。

もしプログラムがS3を使いまくるような設計なら、S3ゲートウェイ追加時には気をつけるべし。

S3ゲートウェイがアタッチされる際、接続中のS3とアプリのコネクションが一時的に中断されるからだ。

例えば頻繁にDockerをデプロイする場合など。

その場合は新しくVPCを作成してS3ゲートウェイを作成するのがベスト。

そして、ECSクラスターとコンテナをそのVPCに統合して頂きたい。

image.png

AWSサービスのリストからcom.amazonaws.region.s3を選択し、ECSクラスタが所属するVPCを選択してS3ゲートウェイエンドポイントを追加する。

Gateway endpointはサブネットのVPCルートテーブルにアタッチされる。

それぞれの「S3ゲートウェイが配置されるべきサブネットに関連したルートテーブル」を選択する。

Gateway endpointはセキュリティグループを使用する代わりに「IAM policy document」を使用する。

これはサービスへのアクセスを制限する為のものだ。

このポリシーはIAMポリシーと似ているが、アプリケーションのデフォルトIAMロールを置き換えるものではない。

ゲートウェイを通しての利用可能なAWSサービスをより詳細に制限する目的なだけだ。

デフォルトであるフルアクセスを使用しても構わない。

image.png

Createを選択してGateway endpointをVPCにアタッチしよう。

サブネットのルートテーブルを見てみると、S3 Gatewayがある。

S3からECR Docker レイヤーイメージがダウンロードされる際は常に使用されることだろう。

AWS PrivateLink interface endpoint for ECSを作る

image.png

ECRからのDockerイメージダウンロードに加え、EC2インスタンスはECSのオーケストレーションの指示を受ける為、ECSとも接続しなければならない。

ECSは次の3つのendpointを必要とする

  • com.amazonaws.region.ecs-agent
  • com.amazonaws.region.ecs-telemetry
  • com.amazonaws.region.ecs

先ほどのECRと同じやり方でこの3つのエンドポイントを作成しよう。

それぞれのエンドポイントをアタッチし、サブネットとセキュリティグループを設定しよう。

エンドポイントが作成され、VPCにアタッチされた後、もう1ステップある。

ECSエージェントがバージョン1.25.1以上であることを確認する。

 ※詳しくはinstructions for upgrading the ECS agent 参照

正しいバージョンでECSエージェントが実行されていれば、VPCで実行中のECSエージェントすべてを再起動しよう。

ECSエージェントとECSバックエンドとの接続はソケットコネクションで接続され続けており、VPCエンドポイントは既存のコネクションに対して接続を中断しない。

リスタートしない限り、エンドポイントとの新規接続ではなく既存のコネクションを使い続ける。

コンテナアプリに影響無くエージェントを再起動するために、SSHでクラスターのEC2に接続して次のコマンドを実行してほしい。

sudo docker restart ecs-agent

このコマンドはホスト上の他のコンテナに影響を与えることなく、ECSエージェントを再起動できる。

ちなみに、エンドポイントを通してECSにアクセスしているわけだが、このアクセスコントロールは現在サポートされておらず、フルアクセスでの接続となる。

※尚、Fargate使用においては

以下2つのエンドポイントのみで良い。

com.amazonaws.region.ecr.dkr
com.amazonaws.region.s3

蓋を開けてみるとCloudWatchのエンドポイントも必要との苦情が多数

image.png

2019/05/08追記
【原因】
英語版の公式サイトには記載あり、日本語版には無い。以上。

まとめ

このサポートの対応前は、EC2インスタンスがDockerイメージをECRからダウンロードしたりECSへアクセスするにはインターネットゲートウェイを使う必要があった。

パブリックIPを持ったパブリックサブネット所属のインスタンスは直接インターネットゲートウェイからプライベートサブネットのインスタンスはNATゲートウェイを使用してアクセスしなければならなかった。

(ちなみにNATゲートウェイはその後、インターネットゲートウェイを通過してECRやECSにアクセスする)

image.png

AWSは爆速で新機能がリリースされて改善されていくので、ついていくのが大変だ。

これからもAWS関連の記事を書いていくので、振り落とされないように一緒に頑張ろう。

image.png

参考:
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/vpc-endpoints.html
https://aws.amazon.com/jp/blogs/compute/setting-up-aws-privatelink-for-amazon-ecs-and-amazon-ecr/

最後まで読んでいただきありがとうございました。

少しでもお役にたちましたらいいねをよろしくお願いします。

宣伝

このたび個人で「会員制コミュニティ付きのAWS初学者を導く体系的な動画学習サービス」
AWS CloudTechをリリースしました。

こちらがご案内動画です。
https://www.youtube.com/watch?v=PppZnHGaChI&feature=youtu.be
無料コースもご用意しておりますので、よろしければ試してみて下さいね!

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
77