0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS CDKで定義したAレコードを変更する

Last updated at Posted at 2023-12-20

この記事はカバー株式会社 Advent Calendar 2023 21日目の記事になります。
カバー株式会社でSREをしているSIです。よろしくお願いします。

はじめに

今回は、ホロプラスのCDK環境でCloudFrontからApplication Load BalancerへRoute53のレコードを変更した際の話について書きます。
本記事ではアーキテクチャなどは紹介しませんのでご興味がある方は、チームメンバーが書いた下記の記事をお読みいただければと思います。

変更前の課題

ホロプラスでは、CloudFrontで全てのAPIアクセスにLambda@Edgeを利用しJWT認証を行なっていましたが、リクエストの度にLambdaがJWT情報の取得を行なっていたためアクセスに300ms ~ 400msの処理時間がかかっていました。
この課題を解決するためにAPI側でJWT認証処理を行うように変更を行うこととしました。
その為、Route53のAレコードを変更しApplication Load Balancerへ直接アクセスを行うように構成を変更することになりました。

Stack状況

ホロプラスのCDK構成はAPIサーバに関するリソースを1つのStack内でAWSが定義するL3 constructsとしてある程度のリソース単位に抽象化を行い定義をしています。

distribution.ts
import { 
  Stack, 
  StackProps, 
  Duration,
  aws_lambda as lambda,
  aws_cloudfront as cloudfront,
  aws_route53 as route53,
  aws_route53_targets as targets,
} from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { Distribution, OriginRequestPolicy, ViewerProtocolPolicy, AllowedMethods, CachePolicy, ResponseHeadersPolicy, LambdaEdgeEventType } from 'aws-cdk-lib/aws-cloudfront';
import { HttpOrigin } from 'aws-cdk-lib/aws-cloudfront-origins';
import { Function } from 'aws-cdk-lib/aws-lambda';

export class MyCloudFrontDistribution extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // Lambda@Edgeの設定(auth Lambda関数)を定義
    const authLambda = new Function(this, 'AuthFunction', {
        stackId: `auth-edge-function`,
        code: lambda.Code.fromAsset('lambda/auth/dist'),
        handler: 'index.handler',
        runtime: lambda.Runtime.NODEJS_16_X,
        functionName: `auth-function`,
    });


    // CloudFrontディストリビューションの作成
    const distribution = new Distribution(this, 'MyDistribution', {
      comment: 'Example service distribution',
      defaultBehavior: {
        origin: new HttpOrigin('example-load-balancer.amazonaws.com', {
          customHeaders: {},
          protocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
        }),
        allowedMethods: AllowedMethods.ALLOW_ALL,
        viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
        originRequestPolicy: new OriginRequestPolicy(this, 'MyOriginRequestPolicy', {
          originRequestPolicyName: 'MyOriginRequestPolicy',
          comment: 'A policy for api',
          cookieBehavior: cloudfront.OriginRequestCookieBehavior.none(),
          headerBehavior: cloudfront.OriginRequestHeaderBehavior.allowList(
            'OS-Version',
            'Accept-Language',
            'App-Version',
            'User-ID',
            'Device-ID',
            'Device-Name',
            'Origin',
            'FCM-Registration-Token',
            'Access-Control-Request-Headers',
            'Access-Control-Request-Method'
          ),
          queryStringBehavior: cloudfront.OriginRequestQueryStringBehavior.all(),
        }),
        cachePolicy: CachePolicy.CACHING_DISABLED,
        responseHeadersPolicy: ResponseHeadersPolicy.CORS_ALLOW_ALL_ORIGINS_WITH_PREFLIGHT,
        edgeLambdas: [{
          functionVersion: authLambda.currentVersion,
          eventType: LambdaEdgeEventType.VIEWER_REQUEST,
        }],
      },
      domainNames: ['api.example.com'],
      certificate: DummyApiCertificate,
      priceClass: PriceClass.PRICE_CLASS_ALL,
      webAclId: DummyWebAclArn,
    });

    // Route53の設定
    if (ExampleZone) {
      new route53.ARecord(this, `ExampleDNSRecord`, {
        recordName: 'api.example.com',
        zone: 'XYZ0123456789',
        target: route53.RecordTarget.fromAlias(
          new targets.CloudFrontTarget(distribution)
        ),
        ttl: Duration.minutes(5),
      })
    }
  }
}

変更方法

先ほどのdistribution.tsに記述しているroute53.ARecordを削除しfargate-api.tsにALBをTargetに変更したリソースとして定義します。

fargate-api.ts
new route53.ARecord(this, `AlbExampleDNSRecord`, {
  recordName: 'api.example.com',
  zone: 'XYZ0123456789',
  target: route53.RecordTarget.fromAlias(
    new targets.LoadBalancerTarget(fargate.loadBalancer)
  ),
  ttl: Duration.minutes(5),
})

デプロイ

実際にデプロイを行なってみると下記のメッセージが出力されました。

        {
            "StackId": "arn:aws:cloudformation:ap-northeast-1:999999999999:stack/dev/60581c90-812e-11ee-9a6a-06dc22ec1947",
            "EventId": "devassethostingdevarecord5960E62B-CREATE_FAILED-2023-11-11T09:46:28.155Z",
            "StackName": "dev",
            "LogicalResourceId": "devassethostingdevarecord5960E62B",
            "PhysicalResourceId": "",
            "ResourceType": "AWS::Route53::RecordSet",
            "Timestamp": "2023-11-11T09:46:28.155000+00:00",
            "ResourceStatus": "CREATE_FAILED",
            "ResourceStatusReason": "[Tried to create resource record set [name='api.example.com.', type='A'] but it already exists]",
            "ResourceProperties": "{\"AliasTarget\":{\"HostedZoneId\":\"Z2FDTNDATAQYW2\",\"DNSName\":\"abcd.cloudfront.net\"},\"Type\":\"A\",\"HostedZoneId\":\"XYZ0123456789\",\"Name\":\"api.example.com.\"}",
            "ClientRequestToken": "5e5876bd7d4c5af1180d6011d6cb8f5f5f8024967e8f423e166dd3bbfe6d7697"
        },

原因

原因はCloud FormationのデプロイフローとしてCreateが完了した後にDeleteが実行されるためdistribution.tsのroute53.ARecord削除が行われていない状態でfargate-api.tsのroute53.ARecordの作成が行われていたためでした。

解決策

RecordSetの情報を確認しているとdeleteExistingというオプションを利用すると解決することがわかりました。
deleteExistingはレコードがある場合は既存のレコードを削除するオプションとなります。
これをfargate-api.tsのroute53.ARecordへ付与すると強制的にレコードを変更することができました。
レコードが変更が完了した後にdeleteExistingを削除してデプロイを行いレコード変更作業は完了となります。

fargate-api.ts
new route53.ARecord(this, `AlbExampleDNSRecord`, {
  recordName: 'api.example.com',
  zone: 'XYZ0123456789',
  target: route53.RecordTarget.fromAlias(
    new targets.LoadBalancerTarget(fargate.loadBalancer)
  ),
  ttl: Duration.minutes(5),
  deleteExisting: true,
})

おわりに

今回は、CDKのレコード変更について書かせていただきました。
レコード変更自体はよくある作業だと思いますので少しでも参考になれば幸いです。
最後まで読んでいただいてありがとうございます。

次回は@kh-coverによる「Unity Editor拡張でPrefabのセットアップを効率化」です。こちらも是非ご覧ください。

0
1
0

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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?