🦈

既存のElastiCache ServerlessをCDK Importするんじゃよ

2024/06/01に公開

要旨

既存のElastiCache Serverlessを安全にCDKにインポートする方法を調べて実現できたので
その時の作業メモです

やりたいこと

手動で作成されたElastiCache Serverless(Redis)をCDKで管理できるようにしたい

やっちゃいけないこと

  • 既存の設定を変える
  • 作り直しを発生させる

手順

大まかな流れ

1.スタックの雛形を作る
2. ElastiCache Serverlessのスタックを書く
3. cdk importを実行
4. CloudFormationでスタックのドリフトを確認
5. 差分が発生していたらCloudFront上でスタックを削除する
6. 差分が発生している部分をコード修正
7. 再度3~6番の手順を差分がなくなるまで繰り返す

スタックの雛形を作る

こんな感じでElastiCache Serverlessが置かれています。これをこれからインポートしていきます
まずはElastiCacheのリソースを入れる箱を用意します

type RedisStackProps = cdk.StackProps &
  {環境ごとの設定とか}
  };

export class RedisStack extends Stack {
  constructor(scope: Construct, id: string, props: RedisStackProps) {
    super(scope, id, props);
  }
}

スタックの雛形をDeploy

cdk cliで作ったスタックをAWSアカウント上にDeployします
CDK Metadataだけがリソースに含まれている状態です

ElastiCache Serverlessのスタックの中身を書く

インポート対象のElastiCache Serverlessの設定を書いていきます。

export class RedisStack extends Stack {
  constructor(scope: Construct, id: string, props: RedisStackProps) {
    super(scope, id, props);

    const vpc = Vpc.fromLookup(this, "VPC", {
      vpcId: props.vpc.id,
    });
    const cacheSecurityGroup = new SecurityGroup(
      this,
      "cache-sg",
      {
        vpc: vpc,
        securityGroupName: "redis",
        description: "Redis from Backend",
      }
    );
    cacheSecurityGroup.addIngressRule(
      Peer.securityGroupId(props.vpc.backend_security_group_id),
      Port.tcp(6379)
    );
    cacheSecurityGroup.addIngressRule(
      Peer.securityGroupId(props.vpc.backend_security_group_id),
      Port.tcp(6380)
    );

    const redisCache = new cache.CfnServerlessCache(
      this,
      "redis-cache",
      {
        engine: "redis",
        serverlessCacheName: "redis-cache",
        description: "redis-cache",
        majorEngineVersion: "7",

        subnetIds: props.vpc.database_subnet_ids,

        securityGroupIds: [
          props.vpc.default_security_group_id,
          cacheSecurityGroup.securityGroupId,
        ],

        snapshotRetentionLimit: 0,
      }
    );
    DressCodeRedisCache.applyRemovalPolicy(RemovalPolicy.RETAIN);
    // ※RemovalPolicyはRETAINにしておく
  }
}

cdk importを実行

AWS上にあるElastiCache Serverlessを入れる箱と設定が完成したので、インポートしていきます
ターミナル上でcdk importコマンドを実行

インポートする対象を確認されるので、あっていたらyes

❯ bun run cdk import CdkPlaygroundStack
$ cdk import CdkPlaygroundStack
CdkPlaygroundStack
CdkPlaygroundStack/RedisCache (AWS::ElastiCache::ServerlessCache): import with ServerlessCacheName=redis-playground (yes/no) [default: yes]? yes
CdkPlaygroundStack: importing resources into stack...
CdkPlaygroundStack: creating CloudFormation changeset...

 ✅  CdkPlaygroundStack
Import operation complete. We recommend you run a drift detection operation to confirm your CDK app resource definitions are up-to-date. Read more here: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/detect-drift-stack.html

インポートが完了しました
CloudFormationの画面を見に行くと
スタックにElastiCache Serverlessが追加されています

※リソースがスタック管理に入ったと言っても、インポート時のコードが実際のリソースに反映されているわけではありません

CloudFormationでスタックのドリフトを確認

インポートが完了したと安心するのはまだ早く、コンソール上で見ながらコードを書いても
実際の設定とコードで設定差分がある可能性があります

CloudFormation上でスタックのドリフトを確認してみましょう
ドリフトが検出されて差分が発生している箇所が分かりました

※cdk importではTerraformのインポート機能のようにdiffチェックやdeploy実行時に、実際のリソースとの差分を確認できる手段はまだありません(202405時点)
実際の差分はCloudFormationのコンソール上で確認する必要があります

ここから先は同じことの繰り返し

差分が出たらスタックを削除

このままだとCloudFormationテンプレートと実際のリソースに差分が発生しているけど
CDKとテンプレートは合致しているのでcdk diffでは差分がない状態になってしまうので
一回スタックを削除します

差分をコード上で解消

ドリフトに出ていた差分をCDKのコード上で解消します

差分を解消したスタックを再デプロイ

差分を解消したコード(リソース作成部分)をコメントアウトして、また雛形を作ります

再インポート

再度インポート作業をして、リソースをCDK管理に移します

再度スタックのドリフトを確認

ここでドリフトが出なくなったらインポート完了です

まとめ

ElastiCache Serverlessのインポート作業をやってみました
CDKのインポートはTerraformと比べてクセがあるなあという印象です
CDKと実際のリソースの間にCloudFormationが挟まっていることで、手順を考えないといけないところがTerraformと比べて多かったです
サービス全体のリソース群をパッケージとして提供するのにCDKはすごい便利だなと思うので
インポート機能の強化期待してます笑

Discussion