【AWS】ECSのサービス検出を作ってみました。【CloudFormation】
こんにちは。インフラ統括部のASUHARUです。
AWSに触れ始めて早半年。
CloudFormationで作成したECSのサービス検出を、備忘も兼ねて共有します。
本記事では初めてECSのサービス検出を構築する方を対象にしています。
ECS自体のテンプレートも記載してますので、初めてECSをCloudFormationで作成される方の参考にもなれば幸いです。
ECSのサービス検出(サービスディスカバリ)とは?
ECSの同一クラスター内で各コンテナ間の名前解決を可能にし、フロントエンドとバックエンドでECS サービスを分離するシステムの構成などで使われる機能です。
他コンテナへアクセスするためのDNS名に対応するレコードを、ECSとRoute 53が自動的に登録してくれます。
オートスケーリングでコンテナが増減した場合でも、連動してRoute 53のレコードが自動的に書き換えられます。
同じような機能としてバック側のコンテナの前にELBを配置し、フロント側ではそのELBに対して名前解決を行う方法があります。
一概にサービス検出がELBの代替にはならず、ELBでのパスルーティングや固定レスポンスの機能はサービス検出では設定できません。
ただコンテナ間での通信のみを目的とするのであれば、ECSの機能のみで解決でき設計時の考慮点が減る点からサービス検出の方が使い勝手が良いかなと思います。
作成【CloudFormation】
前提として起動タイプはFargateを採用します。
また、VPCやセキュリティグループ等は、事前に作成しているものを使用しています。
本記事ではCloudFormationのテンプレートのみ記載しておりますので、スタックの作成方法がご不明な方は以下公式リファレンスをご参照ください。
○作成済みのリソース
・VPC
・サブネット
・セキュリティグループ
・タスク用ロール(「test-ecs-role」)
・タスク実行用ロール(「ecsTaskExecutionRole」)
・ECRリポジトリ(「test-ecr」)
AWSTemplateFormatVersion: 2010-09-09 Description: This CloudFormation template to create ECS # ------------------------------------------------------------# # Parameters # ------------------------------------------------------------# Parameters: ### VPC ID VpcId: Description: Select VPC-ID Type: AWS::EC2::VPC::Id ### Subnet ID SubnetIds: Description: Select two Subnet IDs Type: List<AWS::EC2::Subnet::Id> ### Source Security Group ID SourceSecurityGroupId: Description: Specify the security group ID of the access source. Type: AWS::EC2::SecurityGroup::Id # ------------------------------------------------------------# # Metadata # ------------------------------------------------------------# Metadata: AWS::CloudFormation::Interface: ParameterGroups: ### FunctionConfigration - Label: default: Function Configuration Parameters: - VpcId - SubnetIds - SourceSecurityGroupId # ------------------------------------------------------------# # Resources # ------------------------------------------------------------# Resources: ### ECS Cluster ### ECSCluster: Type: AWS::ECS::Cluster Properties: ClusterName: test-ecs-cluster ClusterSettings: - Name: containerInsights Value: disabled Tags: - Key: Name Value: test-ecs-cluster ### ECS TaskDefinition ### ECSTaskDefinition: Type: AWS::ECS::TaskDefinition Properties: Family: test-ecs-task RequiresCompatibilities: - FARGATE TaskRoleArn: !Sub arn:aws:iam::${AWS::AccountId}:role/test-ecs-role NetworkMode: awsvpc RuntimePlatform: OperatingSystemFamily: LINUX CpuArchitecture: X86_64 ExecutionRoleArn: !Sub arn:aws:iam::${AWS::AccountId}:role/ecsTaskExecutionRole Cpu: 256 Memory: 512 Tags: - Key: Name Value: test-ecs-task ### ECS Container ### ContainerDefinitions: - Name: test-ecs-container Image: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/test-ecr PortMappings: - ContainerPort: 80 Protocol: tcp Essential: true ### ECS Service ### ECSService: Type: AWS::ECS::Service Properties: LaunchType: FARGATE TaskDefinition: !Ref ECSTaskDefinition PlatformVersion: LATEST Cluster: !Ref ECSCluster ServiceName: test-ecs-service SchedulingStrategy: REPLICA DesiredCount: 0 DeploymentConfiguration: MinimumHealthyPercent: 100 MaximumPercent: 200 NetworkConfiguration: AwsvpcConfiguration: SecurityGroups: - !Ref SourceSecurityGroupId Subnets: - !Select [ 0, !Ref SubnetIds] - !Select [ 1, !Ref SubnetIds] AssignPublicIp: ENABLED ServiceRegistries: - RegistryArn: !GetAtt ECSServiceDiscovery.Arn Tags: - Key: Name Value: test-ecs-service ### ECS Service Discovery ### ECSServiceDiscovery: Type: AWS::ServiceDiscovery::Service Properties: HealthCheckCustomConfig: FailureThreshold: 1 DnsConfig: DnsRecords: - Type: A TTL: 30 NamespaceId: !GetAtt ECSPrivateDnsNamespace.Id Name: test-ecs-service
ちなみにタスク実行用ロール(「ExecutionRoleArn」)で選択している「ecsTaskExecutionRole」にアタッチされているポリシー「AmazonECSTaskExecutionRolePolicy」(AWS 管理ポリシー)の権限は以下になります。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ecr:GetAuthorizationToken", "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "*" } ] }
ECRからDockerイメージを取得する場合やコンテナログをCloudWatchへ出力する場合には「AmazonECSTaskExecutionRolePolicy」に含まれている権限が必要となります。
(本記事で構築するECSではECRを使用するためこちらのポリシーを使用しています)
タスク実行用ロールについての詳細やユースケースは公式のドキュメントをご参照ください。
Amazon ECS タスク実行IAM ロール
以下、上記ECSのテンプレート内のサービス検出に関わる部分について説明します。
「ECSPrivateDnsNamespace」は名前空間の設定です。
NameではVPCに紐づく名前空間名を指定します。
VPCにプライベートな名前空間が作成されます。
### ECS Private DnsNamespace ### ECSPrivateDnsNamespace: Type: AWS::ServiceDiscovery::PrivateDnsNamespace Properties: Vpc: !Ref VpcId Name: test-local
次に「ECSServiceDiscovery」の設定です。
ここではECSのサービス検出の設定を行なっています。
サービスの検出名(「Name」)は作成されるDNSレコードのプレフィックスとなる値になります。
「サービスの検出名.名前空間名」となるので、今回の設定では「test-ecs-service.test-local」というDNS名になります。
レコードのタイプについては公式リファレンスに以下のように記載されています。
サービスタスク定義が awsvpc ネットワークモードを使用する場合、各サービスタスクに A または SRV レコードを自由に組み合わせて作成できます。SRV レコードを使用する場合、ポートが必要です。
サービス検出
サービスタスク定義が bridge またはhost ネットワークモードを使用する場合、SRV レコードのみがサポートされる DNS レコードタイプです。各サービスタスクの SRV レコードを作成します。SRV レコードのコンテナ名とコンテナポートの組み合わせをタスク定義から指定する必要があります。
本記事ではレコードのタイプはAレコードを選択しています。
尚、ServiceDiscovery 関連リソースのテンプレート記載方法の参照先は、公式リファレンスの「Cloud Map」のセクションにあります。
AWS Cloud Map resource type reference
ECSServiceDiscovery: Type: AWS::ServiceDiscovery::Service Properties: HealthCheckCustomConfig: FailureThreshold: 1 DnsConfig: DnsRecords: - Type: A TTL: 30 NamespaceId: !GetAtt ECSPrivateDnsNamespace.Id Name: test-ecs-service
挙動確認
作成したテンプレートを基にECSのサービスが構築できたので、挙動を確認していきます。
ECSの「名前空間」にプライベートホストゾーン「test-local」が出来ており、指定したVPCも関連づけられています。
それでは、構築されたホストゾーンにAレコードが作成されるか確認していきます。
ECS サービスのコンソール画面から、「サービスを更新」をクリックします。
更新画面にてデプロイ設定の「必要なタスク」を変更します。
Route 53のホストゾーン「test-local」を確認してみると、Aレコードが一つ作成されています。
試しにタスク数を4つにしてみましょう。
タスク数の増加に連動してAレコードも増加しています。
「必要なタスク」の数を0に変更すると、タスク数の減少に連動しAレコードも削除されました。
ちなみに、Aレコードに割り当てられるIPアドレスについては公式で以下のように記載されています。
パブリック名前空間が使用されている場合でも、 サービス用に作成された DNS レコードは、パブリック IP アドレスではなく、タスクのプライベート IP アドレスに常に登録されます。
サービス検出
まとめ
今回はECSのサービス検出について構築していきました。
便利な機能が多いECS、もっと使いこなしていければと思います。
本記事がECS初学習者の方の参考になれば幸いです。
それでは!