Tech Sketch Bucket of Technical Chips by TIS Inc.

cfn-converterの紹介

Pocket

この記事ではCloudFormation用テンプレートをHeatのCloudFormation互換機能に対応したテンプレートへ自動変換を行うOSSツール「cfn-converter」についてご紹介します。

cfn-converterとは?

cfn-converterはAWS CloudFormation TemplateをOpenStack Heatで使用可能な内容に変換するRuby製のOSSで、現在はの試作段階のためバージョンは0.0.1になります。 このツールはTISが開発を行っているOSSクラウドオーケストレーションツール CloudConductor から派生して作られました。

CloudConductorではパターンを使用してAWSまたはOpenStack上にシステムを構築する機能が実装されており、AWSではCloudFormationを、OpenStackではHeatを使用してシステム構築を行います。 このCloudFormationとHeatには構築するシステムの構成をテンプレートに定義し、それを使用してシステム構築を実行するという共通点があり、更にHeatはCloudFormation用に作られたテンプレートがHeatでも使用できるよう互換性を意識して開発されているので、AWS用のリソースやプロパティが使えるようになっています。 ただし、互換性があると言ってもCloudFormation用テンプレートをそのままHeatで使用できるわけではなく、こちら の公式ページに記載されているとおり、多数のリソースやプロパティが未対応になっており、また、対応しているリソースであっても書き方が限定されている場合があります。 この未対応のリソースやプロパティ、書き方が使われているテンプレートを使用してHeatを実行するとエラーが出てしまうため、CloudFormation用テンプレートをHeatで使用する際には未対応箇所を対応する形式に変換したり、対応している範囲に縮退してやる必要があります。 この作業を自動化する目的でcfn-converterは作られました。

cfn-converterでは未対応リソースの削除を行っている箇所もあるため、変換元のCloudFormation用テンプレートが想定している通りに動作しない可能性があります。 そのため変換元のテンプレートはなるべくHeatに互換性のあるリソースを使用し、Propertyレベルで対応していないものを調整するためにcfn-converterを使用して下さい。

cfn-converterの使い方

環境

この記事では以下の環境で動作確認を行っています。

  • CentOS 6.5
  • Ruby 2.1.1
  • OpenStack IceHouse
    • Heat 0.2.9

インストール

cfn-converterには二通りのインストール方法があります。

gemを使用する場合

Bundlerを使用する場合

コマンド

CloudFormation用テンプレートを変換する際にはcfn2heatコマンドを使用します。 cfn2heatは変換元となるCloudFormationテンプレートを引数として実行する事で、前述したような不要なリソースの削除や書き方の修正を行い、Heatで使用可能なテンプレートを出力します。

このコマンドはCfnConverter::Converters::OpenStackConverterクラスを用いて変換処理を行っています。 独自のConverterクラスを定義した場合には、以下のようにcfnconvコマンドにクラス名を渡すことで独自の変換処理を行うことも可能です。

処理の解説

実際にcfn2heat実行時に行われている処理をAddNetworkInterfaceクラスとRemoveRouteクラスを例に説明していきたいと思います。

AddNetworkInterfaceクラス

CloudFormation用TemplateにはNetworkInterfaceの定義方法として以下の二種類が用意されており、定義できる機能に違いはありません。

しかしHeatでは内部定義型は未対応のため、外部参照型に変更する必要があり、その変換処理を行うのがAddNetworkInterfaceクラスになります。

AddNetworkInterfaceクラスのapply関数内でAWS::EC2::Instanceリソースに含まれるNetworkInterfacesプロパティを抽出する処理を実装しています。 抽出処理は全てのAWS::EC2::Instanceリソースに対して行うのですが、NetworkInterfacesの定義が最初から外部参照型になっている場合は処理を行う必要が無いためnetwork_interface[:NetworkInterfaceId]を条件としてチェックを行っています。

抽出し終わったNetworkInterfacesプロパティからHeatで使用できるプロパティのみ NIC_TEMPLATEにマージし、元になったプロパティからDeviceIndex以外の要素を全て削除します。 最後に NIC_TEMPLATEのkey名を重複しないようにUUIDを使用して作成してテンプレートに埋め込み、NetworkInterfacesプロパティ内にNetworkInterfaceIdと作成したkey名を元にしたRef参照を挿入します。

以上が変換処理の一連の流れになります。 この処理を実行する事で、定義した機能を維持したままHeatでも使用できる形式に変換する事が可能です。

RemoveRouteクラス

CloudFormation用テンプレートではAWS::EC2::Routeリソースを使用して作成するルータに関する設定を定義する事が可能ですが、HeatではAWS::EC2::Routeリソースそのものが使用できません。 更に上で説明したNetworkInterfaceとは違い、互換性のある書き方や他リソースに抽出する、といった対応策もないため、AWS::EC2::Routeリソースが定義されている場合に削除する処理が必要になります。

RemoveRouteクラスに実装されている処理はシンプルで、引数として渡されたテンプレート内からAWS::EC2::Routeリソースを探し、その結果を引数としてリソースを削除する関数remove_resourceを呼び出すだけになっています。

実行結果

では実際にこちらのCloudFormation用テンプレートをcfn2heatコマンドを使用して変換した結果を見てみましょう。

AddNetworkInterfaceクラスによる変換結果

下図は変換前後のテンプレートを比較したものからNetworkInterface周りを抽出したものになります。

NetworkInterface変換比較

上述した内部定義型から外部参照型に書き換わっているのがわかります。

RemoveRouteクラスによる変換結果

下図は変換前後のテンプレートを比較したものからRoute周りを抽出し、わかりやすく加工したものになります。

NetworkInterface変換比較

こちらはAWS::EC2::Routeリソースそのものが削除されているのがわかります。

まとめ

本来であればテンプレートを作成する時にCloudFormationとHeatの両方に対応するよう最初からリソースの互換性を意識しておくことが重要ですが、どうしても両立できないリソースやプロパティも存在します。 この両立できない箇所を手動で修正しようとした場合、数百行規模のテンプレートからOpenStack公式リファレンスを確認しつつ、対応している箇所や未対応の箇所を探し出し手を加えなければなりません。 この手間の掛かる作業をcfn-converterはcfn2heatコマンド一つで行え、更にcfnconvコマンドを使用する事によりユーザが独自に拡張した機能を取り入れることも可能です。 また、今後Heatのバージョンが上がりテンプレートに使用可能なリソースやプロパティが増えた場合cfn-converterに取り入れていく予定です。 皆様もぜひ使用してみてください。


CloudConductor: http://cloudconductor.org/
cfn-converter: https://github.com/cloudconductor/cfn_converter

エンジニア採用中!私たちと一緒に働いてみませんか?