AWS - VPC・IAM・ECSの基礎を学ぶ

2022/06/08に公開

プロダクト開発でAWSを活用するときに、個人ではなくチームとしてAWSの基礎知識を理解している必要がある。

そのような場合に、AWSの基礎知識を理解するための情報を作っておきたいと思う。
ここでは、ECSを中心に使っているプロダクトを想定することとする。

AWSの基礎知識を理解して、活用・運用できる状態

まず、AWSの基礎知識を理解して活用・運用できる状態、をドキュメントなどを読みながら1人でAWSの各サービスが使える状態としたいと思う。

なので、SQS使ったことないけどドキュメント読みながら頑張れば使える、だったり、エラー通知が来たときにドキュメント読みながら解決方法を模索できる、といった状態をイメージしている。
逆に言うと、個別のAWSサービスに関する知識は不要とし、殆どのサービスで共通して必要となる知識を、基礎知識とする。

殆どのサービスで共通して必要となる知識、をVPC・IAMとしてみる。
また、ECSを中心に使っているプロダクトを想定しているので、ECSでVPC・IAMを使ってみる感じで進めることとしてみる。

VPC

VPC

Amazon Virtual Private Cloud(Amazon VPC)とは、AWS上の仮想ネットワークである。
VPCを作成し、そのネットワーク内にEC2・RDSなどのAWSリソースを配置していく。
ただし、VPCに依存しないインターネット経由で利用するAWSサービスも多々ある。

早速、VPCを作成してみる。
VPC名とIPアドレスの範囲(IPv4 CIDR)を指定できる。

IPv4 CIDRとはIPアドレスの範囲を指定する表記方法である。
例えば、10.0.0.0/16などの形式で指定でき、この場合は10.0.0.0の前半16ビットをネットワーク部として使用する形になる。

10.0.0.0
255.255.0.0 (16)
00001010.00000000.00000000.00000000 (10.0.0.0)
11111111.11111111.00000000.00000000 (255.255.0.0)
<---------------> (VPC)

これでVPC(仮想ネットワーク)が作成できた。

サブネット

次に、ネットワーク内にサブネットを作成する。
サブネットとはネットワークを論理的に分割したものである。

AWSではこのサブネットを作成する際に、AZ(Availability Zone)を指定できる。
つまり、複数のサブネットを作成し、それぞれ異なるAZを指定することで、物理的に独立したネットワーク環境を作成でき、より可用性の高いシステムを構築できる。

10.0.0.0
255.255.240.0 (20)
00001010.00000000.00000000.00000000 (10.0.0.0)
11111111.11111111.11110000.00000000 (255.255.240.0)
<--------------------> (Subnet)
<---------------> (VPC)

これでVPC内にサブネットが作成できた。

インターネットゲートウェイ・ルートテーブル

しかし、この状態でVPC内にEC2などを配置してもインターネットにアクセスできない。
なぜなら、インターネットに対してアクセスする経路が作成されていないからである。

インターネットへアクセスするためには、インターネットゲートウェイを作成し、そのゲートウェイへのルーティングを設定する必要がある。

インターネットゲートウェイを作成し、VPCに紐付けます。

ルートテーブルを作成し、サブネットに紐付ける。
作成したルートテーブルを編集し、ゲートウェイへのルーティングを追加する。

これで、サブネットからインターネットゲートウェイへのルーティングが設定され、インターネットへとアクセスできる状態になった。

セキュリティグループ

VPC内にEC2などを配置する際は、セキュリティグループと呼ばれる仮想ファイアウォールを設定する必要がある。
セキュリティグループでは許可する通信のホワイトリストを指定できる。

全ての通信を許可する場合は次のようになる。
任意の通信方法において任意のIP(0.0.0.0/0)からの通信を許可する、Inbound ruleを追加。
任意の通信方法において任意のIP(0.0.0.0/0)への通信を許可する、Outbound ruleを追加。

IAM

IAM(Identity and Access Management)とは、認証・認可のサービスである。
認証とは通信元が誰であるかを確認することで、認可とはアクセス権限を与えることである。

ポリシー

ポリシーとは認可する内容を定義したものである。
具体的には以下のようなJSONで定義できる。
これは、任意のリソースに対するS3操作を許可する、という意味になる。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "*"
        }
    ]
}

もう少し細かく見ていく。
Effectは、許可(Allow)または拒否(Deny)を指定できる。
Actionは、許可・拒否する操作内容を指定できる、s3:PutObjectとすればオブジェクトの更新を指定できる。
Resourceは、操作対象のリソースを指定できる、 arn:aws:s3:::mybucket/*とすれば特定のバケットを指定できる。

UIでポリシーを定義できるので、最初のうちはUIからポチポチして組み立てて行けば良い。

ユーザ・ロール

ポリシーは認可の定義であり、ユーザ・ロールに対して紐付ける必要がある。
ユーザに紐付けたポリシーは、ユーザ自体に適用される。
ロールに紐付けたポリシーは、ロールを受け取ったリソースに適用される。

なので、ロールでは、どのリソースがロールを受け取れるか、を設定できる。
例えば、Lambdaのみロールを受け取れるようにする場合は、以下のようになる。

ECS

ECS(Elastic Container Service)とはコンテナ管理サービスである。
基本的にはECRに登録したコンテナイメージを元に、コンテナを立ち上げていく。
AWS上でいい感じに docker pull して docker run していると思えば良い。

ECR

ECR(Elastic Container Resitory)とは、コンテナ保存サービスである。
AWS版DockerHubと思えば良い。

ここでは以下の内容でコンテナイメージを登録しておく。

index.js
(async () => {
  await fetch('https://jsonplaceholder.typicode.com/todos/1')
    .then(res => res.json())
    .then(json => console.log(json));

  const { ECRClient, DescribeImagesCommand } = require('@aws-sdk/client-ecr');
  const client = new ECRClient({ region: 'ap-northeast-1' });
  await client.send(new DescribeImagesCommand({ repositoryName: 'my-repo' }))
    .then(res => res.imageDetails)
    .then(imageDetails => console.log(imageDetails));
})();
Dockerfile
FROM public.ecr.aws/docker/library/node:18-alpine

WORKDIR /app
COPY index.js ./
RUN npm install @aws-sdk/client-ecr

CMD [ "node", "index.js" ]
$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 999999999999.dkr.ecr.ap-northeast-1.amazonaws.com
$ docker build --platform linux/amd64 -t 999999999999.dkr.ecr.ap-northeast-1.amazonaws.com/my-repo:latest ./
$ docker push 999999999999.dkr.ecr.ap-northeast-1.amazonaws.com/my-repo:latest

クラスター

クラスターとはコンテナ管理する際の論理的なグループである。

クラスターを作成する。

タスク定義

タスク定義とはECSでコンテナを起動するために必要となる情報を定義したものである。
コンテナイメージ・CPU・メモリ、あたりを指定する。
AWS版docker-compose.ymlと思えば良い。

タスク定義を作成する。

タスク・サービス

ECSでコンテナを起動される各コンテナをタスクと呼ぶ。
このタスクは、タスク定義を元に起動でき、クラスターで管理される。

また、同じタスク定義を元に複数コンテナを起動する場合は、サービスと呼ばれる単位でグループ化することができる。
サービスとして扱うと、自動的にコンテナを再起動したり、ALBと連携したりできる。

タスクを起動してみる。
起動する際は、先程作成したVPC・サブネット・セキュリティグループ・タスク定義を指定する。

少しすると起動され、成功すれば以下のようなログが出てくる。

演習

先程、タスクを起動した際に、https://jsonplaceholder.typicode.com/todos/1へのリクエストに成功したログは出ているが、DescribeImagesCommandの成功したログは出ていない。

タスク定義には使用するロールを指定することができる。
ここで指定したロールは、起動したタスクが受け取れるものである。

なので、DescribeImagesCommandのリクエストを成功させるには、適切なアクセス権限をもったロールを指定し、受け取れる必要がある。

実際にロールを作成し、タスク定義で指定し、タスクを起動してみる。

まとめ

IAMたいせつ

Discussion