📚

既存のリソースをIaC化する

2024/07/10に公開

対象

このドキュメントはこのような方々を対象に作成しています。

  • CloudFormationや AWS CDKの概要を理解している
  • 既にAWS CDKを利用してある程度リソースをデプロイした経験がある
  • CloudFormationテンプレートを作成したいが敷居が高いと感じている

目的

開発環境のリソースをコンソール上で作成した後、同様のリソースを本番環境で構築することになりました。

考えていたよりも構築したリソースが多くなったため、今後の運用を見据えて本番環境はIaCで作成したいと考えました。

移行するIaCツールはCDKを検討していますが、まだCDKを使いなれていないので現行環境をパラメータに落とし込むには時間がかかります。

そこで既存のリソースをCloudFormationテンプレートに出力してCDKのコードに変換出来ればよいのでは?と考えました。

既存リソース → CFnテンプレート → CDK化

IaCジェネレータを使用する

CloudFormationにはIaCジェネレータという機能があります。

これはCloudFormation以外で作成された既存のリソースをCFnテンプレート化するものです。

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/generate-IaC.html

使用するために特に準備は必要ありませんが、要否を判別するためIaC化しておきたいリソースにタグををつけておくとよいでしょう。

まずはリソースのスキャンを開始します。
CloudFormation > IaCジェネレーター > 新しいスキャンを開始

作成するテンプレートはこのスキャンを実施した時点のものとなります。

スキャンはアカウント上のすべてのリソースをプロビジョニングするため時間がかかります。

次に、スキャンしたデータからテンプレートを作成します。

テンプレートにスキャンしたリソースを追加します。

必要なリソースタイプやタグなどを絞り込んで追加していきましょう。

ここで、「関連リソースを追加」することで依存関係を選択することができます。

テンプレートを作成ボタンを押下します。

なお、テンプレートを作成後もリソースの削除や追加、再同期が可能です。

テンプレートが完成しました。

このままでは可読性が低いので、CDKテンプレートに変換します。

CFnテンプレートをCDKのコードに変換

CDKのアプリケーション用を配置するディレクトリに移動してmigrateコマンドを実行し、先ほどのテンプレートを変換します。

テンプレートを変換する前に環境名やパラメータの変更がある場合は、適宜修正・削除してください。

CDK Migrateの使い方は下記の記事に記載されています。

https://aws.amazon.com/jp/blogs/news/announcing-cdk-migrate-a-single-command-to-migrate-to-the-aws-cdk/

cdk migrate --stack-name CDK-Local-Template-Migrate-Demo --language typescript --from-path ./demo-template.yaml

先ほど出力したテンプレートのタブからCDK用の実行コマンドをコピーできるので、こちらを利用してもよさそうです。

cdk migrate --stack-name my-cf-templete-dev --from-path ./my-cf-templete-dev.yaml --language typescript

コマンドを実行します。

このまま移行先アカウント用のアプリケーションを作成しようとしましたが、アカウントIDなど依存するパラメータがあるため直接変換はできませんでした。

cdk migrate --stack-name my-cfn-cf-stack --language typescript --from-path ../../cfn/my-cfn-cf-resources-dev.yml --profile prod
This command is an experimental feature.
   Migrate failed for `my-cfn-cf-stack`: Template with arn arn:aws:cloudformation:ap-northeast-1:123412341234:generatedTemplate/3584a721-89fe-4b58-94f9-xxxxxxxxxxxx does not exist (Service: CfnTemplateGenerationServiceLambda; Status Code: 400; Error Code: GeneratedTemplateNotFoundException; Request ID: 531d8c3e-691b-4425-90fe-357920113cd4; Proxy: null)

Template with arn arn:aws:cloudformation:ap-northeast-1:123412341234:generatedTemplate/3584a721-89fe-4b58-94f9-xxxxxxxxxxxx does not exist (Service: CfnTemplateGenerationServiceLambda; Status Code: 400; Error Code: GeneratedTemplateNotFoundException; Request ID: 531d8c3e-691b-4425-90fe-357920113cd4; Proxy: null)

どうやらテンプレートに記載されたメタデータに検証環境のアカウントIDが記載されているため、エラーが発生したようです。

---
Metadata:
  TemplateId: "arn:aws:cloudformation:ap-northeast-1:123412341234:generatedTemplate/3584a721-89fe-4b58-94f9-xxxxxxxxxxxx"

このままでは本番環境に移行ができないため、こちらを修正してもう一度試します。

下記のようなメッセージが出力されて、CDKアプリケーション化に成功したようです。

cdk migrate --stack-name my-cfn-cf-stack-prod --language typescript --from-path ../cfn/my-cfn-cf-resources-dev.yml --profile prod
This command is an experimental feature.
 ⏳  Generating CDK app for my-cfn-cf-stack-prod...
Applying project template app for typescript
Initializing a new git repository...
Executing npm install...
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
✅ All done!

完成したコードを見てみます。
TypeScriptが分からなくてもコードが生成できましたが、環境依存部分や変数化するべき部分などは修正が必要です。

import * as cdk from 'aws-cdk-lib';
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';

export interface MyCfnCfStackProdStackProps extends cdk.StackProps {
}

export class MYCfnCfStackProdStack extends cdk.Stack {
  public constructor(scope: cdk.App, id: string, props: MyCfnCfStackProdStackProps = {}) {
    super(scope, id, props);

    // Resources
    const cloudFrontCachePolicy = new cloudfront.CfnCachePolicy(this, 'CloudFrontCachePolicy', {
      cachePolicyConfig: {
        comment: 'Policy with caching disabled',
        minTtl: 0,
        maxTtl: 0,
        parametersInCacheKeyAndForwardedToOrigin: {
          queryStringsConfig: {
            queryStringBehavior: 'none',
          },
          enableAcceptEncodingBrotli: false,
          headersConfig: {
            headerBehavior: 'none',
          },
          cookiesConfig: {
            cookieBehavior: 'none',
          },
          enableAcceptEncodingGzip: false,
        },
        defaultTtl: 0,
        name: 'Managed-CachingDisabled',
      },
    });
    ....

まとめ

今回の検証でIaCジェネレーター機能を利用するとCloudFormationの知識がなくてもリソースをIaC化出来る事が分かりました。

ある環境からほかの環境へAWSリソースを移行をする際、パラメータの反映漏れなどが発生することがあります。

これを防ぐためにリソースのパラメータシートを作成したり、移行前後の環境を目視で確認することは手間がかかりますよね。

IaCによって環境を可視化することで環境移行の際に抜け漏れを防ぎやすくなると思います。

IaC化を思い立った方は、ぜひこちらの手順でインフラをCDKアプリケーションからデプロイしてリソースを作成してみてください。

株式会社トッカシステムズ

Discussion