Sock ShopのCloudFormation TemplateをTerraformとPulumiに移植した

Microservices Demo: Sock Shopの CloudFormation TemplateをTerraformとPulumiに移植したので、それに関するメモを残しておく。


モチベーション

最近仕事ではTerraformを触っている時間が一番多いので、研究もこの辺りのツールに関連する技術を対象とした方が良いのでは、と考えた。研究を行うためには、類似ツールの比較が必要だし、比較のためには、サンプルコード程度のものではなく、実際の環境に近い状態を再現できるコードが必要、というのが移植のモチベーションになっている。


移植元コード

Deployment on Amazon EC/2 Container ServiceにAmazon ECSへのデプロイ手順が載っているが、肝心のCloudFormation Templateは、元リポジトリではDeplicated扱いで削除されている

なので、markfink-splunk/sock-shop: Deployments of the Weaveworks Sock Shop application instrumented with SignalFx.にあるファイル(ecs-fargate/cfn-stack-app-only.yaml)を移植元コードとして使うことにした。


デプロイ環境

個人用に使っている検証用AWSアカウント、惰性で使っていてぐちゃぐちゃになってきたので、いったん不要なリソースを全削除して、AWS Organizationsでマルチアカウント化、AWS Single Sign-Onで各アカウントにSSOできるようにした。

アカウント管理用のTerraformコード、最初はprivateにしていたけど、別に見えてまずい情報もないな、と思ったのでpublicにした

これにより、CloudFormation、Terraform、Pulumiそれぞれの検証環境をアカウントごと分離できるようにした。


CloudFormation Templateのデプロイ

まずは大元となるCloudFormation Templateがデプロイできるものになっていないと話にならないので、ここから着手。元ファイルのままでは動かなかったり、そのままでは不便なところなどあったので、微修正している。差分は以下の通り。


Terraformへの移植

CloudFormation Templateがデプロイできたところで、Terraformへの移植を行った。移植はおおまかには以下のような手順で行った。

  1. リソースをひとつ選び、Terraformコードで必須Argumentだけ指定したリソースを定義。
  2. terraform importでCloudFormation用アカウント上のリソースをimport。
  3. terraform planでCloudFormation用アカウント上のリソースとの差分を確認し、差分がなくなるよう必須以外のArtumentsを記述。
  4. 差分がなくなったらTerraform用アカウントにterraform applyしてリソースを作成。

上記の作業を80ほどあるリソース全てに対して行った。

Terraformerはいまいち使い勝手が悪いし、ひとつひとつどのようなリソースがあるか確認しておいた方が、後々捗りそうなので、人力で移植した。

先日行われたHashiTalks: 日本での、Quipperの鈴木さんのプレゼンで知ったtfmigratorを使えば、Terraformerのいまいちさを補えたっぽいので、今度機会があれば使ってみたい。

Terraformerがどういまいち使い勝手が悪いのか、とか、tfmigratorの使い方なんかは、鈴木さんのブログエントリに詳しく書いてあるので、興味ある方はこちらからどうぞ。

移植の最終確認として、Terraform用アカウントにapplyしたリソースをいったんdestroyして、最初から全リソースのapplyを行った。

が、上記手順4で「差分がなくなるよう必須以外のArgumentsを記述」とあるが、planで差分がなくなっても、別アカウントにapplyすると、明示してないArgumentが原因でうまくapplyできないリソースがあったので、その辺りの修正を行った。


Pulumiへの移植

Pulumiへの移植も、Terraformへの移植と同様に、CloudFormation用アカウント上のリソースをひとつひとつインポートしながら進めていった。

tf2pulumicf2pulumiといったツールもオフィシャルに提供されているけど、自分がわかりやすいようにコードやファイルを分割したかったので、これらのツールは使わなかった。

PulumiはTypeScript、JavaScript、Python、Go、C#から記述言語が選べるが、この中で一番慣れているGoで記述を行った。

Pulumiのリソースインポートは、Terraformと違いコードの生成まで行ってくれる。

たとえば、

 $ pulumi import aws:cloudwatch/logGroup:LogGroup \
  sock_shop \
  sock-shop

といったコマンドでCloudWatch Logs log groupをインポートすると、以下のようなコードを吐いてくれる。

ただ、pulumi importではエラーになってうまくインポートできない場合もあり、そういう場合は、先に以下の様なコードを書いてから、pulumi upを実行してインポートした。最後のpulumi.Import()がポイント。

また、希にpulumi importが吐くコードが間違っていることもあって、そういう場合は手で修正を行った。

Pulumi、サンプルコード程度しか触ったことがなかったけど、今回の移植作業でだいぶ把握できた気がする。


まとめ

最初の方でもリンクを張っているけど、移植したコードはここに置いてあります