Terraform stateファイル管理用のリソース(S3,DynamoDB)作成のCFnをService Catalogに登録してみる

2023.01.30

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

「Terraform Backend用のリソースをService Catalogで管理したら便利かも」

個人的にはTerraform Cloudでstateファイルを管理する方法が好きですが、S3とDynamoDBを使用することがあると思います。

このリソースは、Terraform以外の方法で作成する必要があります。(stateファイルどこに置く問題が発生するため)

毎回手動でS3とDynamoDBを作るのは面倒なので、CloudFormation(以下CFn)テンプレート化してみました。 CFn化したことで楽にはなったんですが、組織内で楽に共有する方法はないかなと探していたらService Catalogを見つけました。

Service Catalogを使うことで、AWSのコンソール上からお手軽にTerraform state管理用のリソースをデプロイできます。

やってみた

ブログ中のコードは以下にあります。

msato0731/terraform-backend-cfn

CFnテンプレートの用意

state保管用のS3バケットと、排他制御用のDynamoDBを用意するCFnテンプレートです。

必要最低限のリソース定義になっています。

もっと細かく設定したい場合は、以下のリポジトリが参考になると思います。 (例えば、S3バケットの暗号化にSSE-KMSを使いたい等)

thoughtbot/cloudformation-terraform-state-backend: Cloudformation template to create Terraform state S3 backend

terraform-backend.yml

AWSTemplateFormatVersion: "2010-09-09"
Description: S3 & DynamoDB for Terraform Backend

Parameters:
  Name:
    Description: |
      Name of the S3 bucket, DynamoDB table;
      Defaults to "terraform-state-AWS_ACCOUNT_ID"
    Default: ""
    Type: String

Conditions:
  GenerateNames: !Equals [!Ref Name, ""]

Resources:
#------------------------------------------------------------------------------#
# S3
#------------------------------------------------------------------------------#
  StateBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
    UpdateReplacePolicy: Retain
    Properties:
      BucketName: !If
      - GenerateNames
      - !Sub "terraform-state-${AWS::AccountId}"
      - !Ref Name
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      LifecycleConfiguration:
        Rules:
        - Id: ExpireOldVersions
          NoncurrentVersionExpirationInDays: 90
          Status: Enabled
      VersioningConfiguration:
        Status: Enabled
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: "AES256"
#------------------------------------------------------------------------------#
# DynamoDB
#------------------------------------------------------------------------------#
  LockTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: !Ref StateBucket
      ProvisionedThroughput:
        ReadCapacityUnits: 1
        WriteCapacityUnits: 1
      AttributeDefinitions:
        - AttributeName: "LockID"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "LockID"
          KeyType: "HASH"

Service Catalogで製品を登録

マネジメントコンソール > Service Catalog > 管理者 > 製品リスト > 製品を作成の順に選択します。 以下のように、必要な情報を入力します。

今回はGithubリポジトリにCFnのファイルを置いているので、CodeStarを使ってリポジトリと接続します。

ポートフォリオの作成

製品をプロビジョニングするために、ポートフォリオを作成します。

Service Catalogの画面から管理者 > ポートフォリオ > ポートフォリオの作成の順に選択します。

以下のように情報を入力します。

ポートフォリオを作ったら、最初に作った製品を登録します。

最後にポートフォリオにアクセスできるように設定します。

今回はIAMロールにポートフォリオへのアクセス権限を付与しました。

製品をプロビジョニングする

準備が整ったので実際に製品をプロビジョニングして、Terraform State管理用のリソースを作成します。

Service Catalogの画面からプロビジョニング > 製品 > terraform-state-backend > 製品を起動の順に選択します。

リソースを作成できました。

補足

製品のバージョンアップ

外部リポジトリと接続している場合は、以下のように外部リポジトリ側で変更があるとバージョンが追加されます。

製品プロビジョニング時は、最新のバージョンがデフォルトで選択されます。

自動で追加されたバージョンには、製品バージョンが振られていません。

手動でバージョン情報をを設定することが可能です。 少し面倒ですが、運用上バージョン情報はあった方が良いため設定することをおすすめします。

CFnが使われているので、バージョンアップ前のリソースとバージョンアップ後のリソースで差分を確認することもできます。(変更セットみたいなイメージ)

組織内に共有する

Service Catalogのポートフォリオはアカウント間で共有もできます。

組織内の別アカウントで展開する場合は、ポートフォリオの設定を更新する必要があります。

詳細な手順は以下のブログがわかりやすいです。

おわりに

Terraformのstate管理用のリソースをService Catalogを使って作る手順でした。

組織のアカウントに共有しておけば、セルフサービス化が捗ると思いますので検討してもらえればと思います。

似たようなことはAWS Protonでもできますが、私としては単純にCFnをカタログ化したいだけならService Catalogの方が楽という感覚です。 (Protonでは、CFnをProton用にカスタマイズする必要があるため)

アカウント数が多くなるとこの方法でもstate管理のリソース自体の管理も大変になってくると思います。

その場合は、Terraform Cloudの利用を検討してみてください。

Terraform Cloud側でstateファイルを管理することが可能なので、今回のようにリソースを作る必要がありません。

ちなみに、stateファイルをTerraform Cloudに移すことはFreeプランでも試すことができます。

以上、AWS事業本部の佐藤(@chari7311)でした。