AWSを利用したシステムに関して、構成管理ツール・デプロイツールの使い方が「複数サーバへの一括パラレル配信どやー!」といった時代ではなくなってきていると感じています。
イミュータブルインフラストラクチャーとブルーグリーンデプロイメントが完全に機能する世界、良いですね!AMIを中心に据えた構成管理とデプロイに関しては、すでに冪等性さえもどうでもよいことが多いのではないでしょうか。
しかし、現時点でそういった仕組みを用意している構成管理・デプロイツールがあるような気がしていないので、 Oozappa にテンプレート的な機能を追加したいと思うのです。このエントリはそのプロポーザル的なものです。
AWSの世界はこうなってると思っている
ビルディングファームVPC
サービスで稼働するインスタンスは、サービスと関係の無いVPC(Virtual Private Cloud)でビルドされる。ビルディングファームVPCはそのためだけのVPCで、VPCには、1つのsubnetと、構成管理ツールを起動するマシンや開発拠点からのSSHのみを許可するsecurity groupがあれば良い。
Vanilla AMI
Vanilla Instanceは、Cloud AMI(AWS提供の素のAMI)をビルディングファームVPC上に起動し、自分の開発・提供するシステム・サービスにおいて基本となる設定のみを施した状態のインスタンスと定義する。
例えば、 Development Tools をyumで入れたり、 build-essential を apt で入れたり、Python3.5.1をビルドしたり、supervisordとかcircusとか、mysqlのクライアントを入れたりといった頻度は高くなくてそこそこ時間のかかる共通処理を行ったインスタンスです。
インスタンスの準備ができたらAMIを作ってインスタンスは消してしまいます。
Vanilla AMIのタグ Tag name | Value | Description | Name | SERVICE-Vanilla-yyyyMMdd-HHmmss | AWS Consoleで識別するための名前 | Service | サービス名 | 単一のサービスでも入れておくと後で助かるので入れるべき | Serial | 0000n | シーケンシャルにカウントアップしていき、最新を見分けるためのもの | Role | Vanilla | Vanillaフレーバーのものを表す |
タグをつけておいて、Role用のAMIを作るときに検索キーにします。
Role AMI
Role Instanceは、最新のVanilla AMIをビルディングファームVPC上に起動し、アプリケーションのデプロイと、該当アプリケーションに必要なライブラリやモジュール、ログの日数の設定など細かい設定を施したものが Role AMI です。アプリケーションと設定ファイル以外の準備をしたHalf Bakedな状態があっても良いかもしれません。
インスタンスの準備ができたら、設定ファイルを差し替えながら各環境用のAMIを作ってインスタンスは消してしまいます。
各環境というのは、開発環境用・ステージング用・プロダクション用などです。全く同じものから作っているので設定ファイル以外は差異はゼロです。もし、最終的にAMIからサービス用のインスタンスを起動するときに設定ファイルへのポインタを変更するuser dataを用いるのであれば、各環境用ではなく、Role毎にAMIを1つ作れば良いですね。ただし、user dataは確認が面倒なので、できるだけ変更は加えたくない気持ちがあります…。
Role AMIのタグ Tag name | Value | Description | Name | SERVICE--ENVIRONMENT-ROLE-yyyyMMdd-HHmmss | AWS Consoleで識別するための名前 | Service | サービス名 | 単一のサービスでも入れておくと後で助かるので入れるべき | Serial | 0000n | シーケンシャルにカウントアップしていき、最新を見分けるためのもの(Service+Role毎) | Role | Application等 | インスタンスの役割を表すもの | Environment | Production等 | どの環境用に設定されているかを表す | Base Vanilla AMI | SERVICE-Vanilla-yyyyMMdd-HHmmss | 元になったVanilla AMIの情報 | Base Vanilla Serial | 0000n | 元になったVanilla AMIの情報 |
こちらもタグをつけておいて、自動起動設定などを作るときに検索キーにします。
絵にするとこんな感じ
Ansibleを使った場合、ec2を起動して、起動したインスタンスの情報をregisterで変数に格納して…、変数のスコープ変わったら検索してregisterで…、aws用のfact系モジュールが足りないので結局botoで書いたスクリプトをlibraryフォルダに入れて(2.1で入るやつとかあるので早く2.1出して〜)、みたいにクラウド用には使いにくく感じます。同じようなモジュールを使う指示を同じPlaybookの中に何度も書くことになったり、1度しか使わないroleなのにファイルが分散して、Oozappaで書くよりもとっ散らかる感じがあります。これは、AMIを使ったクラウドという世界ではなく、モジュールの再利用や、同じ物理マシンへ何度もPlaybookを実行する必要があるために冪等性といったことを重視したものだからと思われます。つまり、AWSの頻出パターンに使うべきプロダクトではないのです(ある若者がOozappaからAnsibleへ乗り換えを試みてから戻ってきたのはこういうことだったのかな)。
各環境用のVPCとインスタンスの投入
ビルディングファームは別にあるので、各環境用のVPCやELBなどをつくるのですが、基本的にはネットワークなどが違うだけなので設定を切り替えてちょちょいとやれば良いはず。そのあたりの考え方も Oozappa の構成の方がマッチしている(まぁ、自由なんだけれども)と思っています。
実際のサービスや開発環境などにインスタンスを投入するのは、すでにつくってあるRole AMIをAutoscallingに設定をしたり、別途botoをラップしたジョブセットなどで起動して入れ替えたりするだけです。もはやインスタンスへはデプロイのためのSSHログインさえも(もちろんプロビジョニング用のエージェントさえも)必要なく、AWS上の権限に関してはインスタンスに環境毎のResourceに制限したAMIを割り当てて起動すれば非常に美しい状態になります。
まとめ
FabricのPython3対応が非常に微妙な感じなので、すでにPython3で動くタスクランナーのInvokeをうまくつかってOozappaもOozappa2的にしてAWSに特化したものに新たに作り直すかもしれません。面倒なのでOozappaにAWSテンプレート的な機能を追加するかもしれません。なにもしないかもしれません。かもしれません。かもしれません。
※ わかってねーなー。仕方ねーし、一緒に働いてやるよ!って人は声かけてください!
※ それとはべつに Oozappa をマシにしたいって人がいたらorganization作ったのでそっちに移すことも考えるくらいまともなことを言ってみてください。