
AWS(Amazon Web Services)を真剣に使用している場合、JSONテンプレートを使用してインフラストラクチャを記述する機能についておそらくご存知でしょう。 AWSでは、このサービスは
CloudFormationと呼ばれます。 本質的に、このソリューションでは、AWSで利用可能なリソース(インスタンス、opsworks、ELBレイヤー、セキュリティグループなど)の望ましい状態を記述することができます。 リソースのセットはスタックと呼ばれます。 CloudFormationテンプレートを読み込んだ後、システム自体が必要なリソースをスタック上に作成します(まだ存在しない場合)、または既存のリソースを目的の状態に更新しようとします。
これは、リソースが少ない場合はうまく機能しますが、インフラストラクチャが拡大するとすぐに問題が発生します。
- JSONでは、ループを使用することはできません。同様のリソースでは、変更の場合も同じパラメーターを繰り返す必要があります(DRYではない)
- cloud-initの構成を記述するために必要な二重エスケープ
- JSONにはコメントがなく、人間の可読性が低い
このような問題を回避するために、
Heavy Waterのエンジニアは、Ruby DSLおよびCLIで
SparkleFormation (
github )と呼ばれるこれらのテンプレートを生成および操作するように書きました。
ドライ
現在のプロジェクトに来たとき、約1,500行のリソース記述と約0行のコメントを含むCloudFormationテンプレートがありました。 SparkleFormationを使用した後、テンプレートは300行を占有し始めましたが、その多くはコメントです。 どのようにしてこれを達成しましたか? まず、CloudFormationの仕組みを見てみましょう。典型的なリソースの説明は次のようになります。
ELBの作成"AppsElb": { "Type": "AWS::ElasticLoadBalancing::LoadBalancer", "Properties": { "Scheme": "internal", "Subnets": [ {"Ref": "Subnet1"}, {"Ref": "Subnet2"} ], "SecurityGroups": [ {"Ref": "SG"} ], "HealthCheck": { "HealthyThreshold": "2", "Interval": "5", "Target": "TCP:80", "Timeout": "2", "UnhealthyThreshold": "2" }, "Listeners": [ { "InstancePort": "80", "LoadBalancerPort": "80", "Protocol": "TCP", "InstanceProtocol": "TCP" }, { "InstancePort": "22", "LoadBalancerPort": "2222", "Protocol": "TCP", "InstanceProtocol": "TCP" }, { "InstancePort": "8500", "LoadBalancerPort": "8500", "Protocol": "TCP", "InstanceProtocol": "TCP" } ] } }
SparkleFormationではDSL内で通常のルビーコードを使用できるため、次のように書き換えることができます。
SparkleFormationでELBを作成する resources(:AppsElb) do type 'AWS::ElasticLoadBalancing::LoadBalancer' properties do scheme 'internal' subnets [PARAMS[:Subnet1], PARAMS[:Subnet2]] security_groups [ref!(:SG)]
ご覧のとおり、各ポートの説明はもう繰り返さないため、新しいポートを追加しても1行だけで済みます。 さらに、多くのほぼ同じリソースを作成する必要があるが、パラメーターが1〜2異なる場合、SparkleFormationはそのようなエンティティーをダイナミクスとして提供します。
ドキュメントの例
そして、テンプレート内でこの抽象リソースを呼び出すことができます。
SparkleFormation.new(:node_stack) do dynamic!(:node, :fubar) dynamic!(:node, :foobar, :ssh_key => 'default') end
したがって、必要なリソースを再利用し、必要に応じてすべてを1か所で変更できます。
クラウド初期化
cloud-initをロードするときにyamlファイルの形式で設定を転送し、それを使用してパッケージをインストールし、CoreOS、個々のサービスおよびその他の設定を設定する機会をしばしば利用します。 問題は、yamlがインスタンスをCloudFormationテンプレートのユーザーデータに渡す必要があることで、次のようになります。
クレイジーエスケープ "UserData": { "Fn::Base64": { "Fn::Join": [ "", [ "#cloud-config\n", "\n", "coreos:\n", " etcd:\n", " discovery: ", {"Ref": "AppDiscoveryURL"}, "\n", " addr: $private_ipv4:4001\n", " peer-addr: $private_ipv4:7001\n", " etcd2:\n", ...
ご覧のとおり、構文の強調表示を忘れる可能性があることは言うまでもなく、これは絶対に判読できず、見苦しく、メンテナンスが不十分です。 DSL内でrubyコードを使用できるため、yaml全体を別のファイルに移動して、単に呼び出すことができます。
user_data Base64.encode64(IO.read('files/cloud-init.yml'))
ご覧のとおり、これはJSON内で編集するよりもはるかに優れています。 IO.readの代わりに、必要に応じて任意のパラメーターにHTTP呼び出しを使用できます。
CLI
このプロジェクトでは、テンプレートを管理するために独自のラッパーを使用しますが、この同じコマンドは
sfnと呼ばれるテンプレートを管理するためのCLI(コマンドラインインターフェイス)を提供します。 これを使用すると、sfn create、sfn destroy、およびsfn updateコマンドを使用してCloudFormationスタックをダウンロード、削除、および更新できます。 ナイフとの統合も実装されています。
一般に、SparkleFormationを4か月使用した後は満足しています。インフラストラクチャを説明するために単純なJSONに戻らないことを願っています。 計画は、Heavy Waterチームが提供するsfnを含むワークフロー全体を試すことです。