Ansibleからaws cliを実行する
渡辺です。 AnsibleによるAWSリソースの構成管理シリーズの5回目は、どうしても避けられない新機能のサポートに関わるトピックです。
AWSの新機能とツールのサポート時期
AWSでは毎週のように新機能がリリースされています。 非常に魅力的な新機能も多く、「これが欲しかったんだ!」と思うこともしばしばです。 一方、原則としては新機能がデフォルトで有効になることはありません。 既存のシステムの挙動が変わり、トラブルになる可能性を考慮すれば当然でしょう。
新機能を利用するには、明示的に、マネジメントコンソールなどを利用して設定を行わなければなりません。 各インターフェイスの提供時期は概ね次のようになります。
インターフェイス | 時期 | 説明 |
---|---|---|
AWS CLI | 即 | 新機能リリースと同時 |
AWS SDK | 早 | 新機能リリースと同時が多い |
マネジメントコンソール | 早 | 新機能リリースと同時が多いが、遅れる場合もある |
CloudFormation | 並 | 数ヶ月程度で対応する場合も多いが、なかなか提供されないこともある |
サードパーティツール | 遅 | Ansibleなど、リリースサイクルに依存 |
AWSはAPIを重視しているため、原則としてAWS CLIは新機能のリリースと同時にその機能に対応します。 またSDKやマネジメントコンソールも、新機能のリリースとほぼ同時に利用できることがほとんどです。
CloudFormationはAWSの純正ツールになりますが、新機能のサポートタイミングはまちまちです。 なかなかサポートされないケースもあるのが現実です。
一方、Ansibleなどサードパーティーツールでの新機能サポートは遅れがちです。 AWSの新機能リリースのサイクルが早く多いため追いつくのが難しいというのが現実でしょう。 このため、「XXで構成管理はしているけどZZ機能をサポートしていないので、そこは手組で…」となりがちです。 ここがサードパーティーツールを利用する時のジレンマとなっています。
AnsibleからAWS CLIを叩く
Ansibleの強みはモジュールが充実しており、簡潔な設定ファイルで構成管理を行うことです。 しかし、構成管理上、直接スクリプトやコマンドを実行せざるを得ないケースは少なからずあり、Ansibleではそれらをshellモジュールやcommandモジュールを利用してカバーできます。 勿論、モジュールで実現できる範囲はモジュールを利用すべきですが、どうしようもない場合はshellモジュールやcommandモジュールを利用します。
そう、モジュールでサポートされない新機能は、AWS CLIを叩けばいいのです。
サンプルとして、VPCピアリングのDNSサポート機能をAnsibleから有効にしてみたいと思います。
リソースのステータスを取得し、冪等性を保つ
command系モジュールを利用するポイントは、チェックと更新のタスクをそれぞれ定義することです。
はじめにaws ec2 describe-vpc-peering-connections
コマンドで、AllowDnsResolutionFromRemoteVpc
の値を取得します。
コマンドラインから実行するのであれば次のようなコマンドです。
aws ec2 describe-vpc-peering-connections \ --vpc-peering-connection-id pcx-xxxxxxxx --profile hogehoge
実行結果はJSONでこんなイメージです。
{ "VpcPeeringConnections": [ { "Status": { "Message": "Active", "Code": "active" }, "Tags": [], "AccepterVpcInfo": { "PeeringOptions": { "AllowEgressFromLocalVpcToRemoteClassicLink": false, "AllowDnsResolutionFromRemoteVpc": false, "AllowEgressFromLocalClassicLinkToRemoteVpc": false }, "OwnerId": "xxxxxxxx", "VpcId": "vpc-xxxxxxxx", "CidrBlock": "10.0.0.0/16" }, "VpcPeeringConnectionId": "pcx-xxxxxxxx", "RequesterVpcInfo": { "PeeringOptions": { "AllowEgressFromLocalVpcToRemoteClassicLink": false, "AllowDnsResolutionFromRemoteVpc": false, "AllowEgressFromLocalClassicLinkToRemoteVpc": false }, "OwnerId": "xxxxxxxx", "VpcId": "vpc-xxxxxxxx", "CidrBlock": "10.1.0.0/16" } } ] }
--query
オプションでRequesterVpcInfo
のAllowDnsResolutionFromRemoteVpc
を抽出します。
aws ec2 describe-vpc-peering-connections \ --vpc-peering-connection-id pcx-xxxxxxxx --profile hogehoge \ --query VpcPeeringConnections[0].RequesterVpcInfo.PeeringOptions.AllowDnsResolutionFromRemoteVpc
AWS CLIで確認したならば、Playbookのタスクとしてregister
で結果を保持します。
- name: check DNS Options / Requester command: "aws ec2 describe-vpc-peering-connections --vpc-peering-connection-id {{ _vpc_peer.peering_id }} --profile {{ profile }} --query VpcPeeringConnections[0].RequesterVpcInfo.PeeringOptions.AllowDnsResolutionFromRemoteVpc" changed_when: False register: _dns_options_vpc_peer_req
冪等性を確保したいので、changed_when
をFalse
に設定することを忘れないでください。
AWS CLIでリソースを更新する
チェックした値を元に、必要があればAWS CLIを利用してDNSオプションを有効化します。
有効化するためのコマンドは次のようになります。
aws ec2 modify-vpc-peering-connection-options \ --vpc-peering-connection-id pcx-xxxxxxxx --profile hogehoge \ --requester-peering-connection-options AllowDnsResolutionFromRemoteVpc=true
--dry-run
オプションを付与してコマンドラインから実行確認します。
確認したならば、Playbookのタスクを定義しましょう。
- name: Modify Peering Options / Requester command: "aws ec2 modify-vpc-peering-connection-options --vpc-peering-connection-id {{ _vpc_peer.peering_id }} --profile {{ profile }} --requester-peering-connection-options AllowDnsResolutionFromRemoteVpc=true" when: _dns_options_vpc_peer_req.stdout == 'false'
チェック時にコマンドの実行結果を_dns_options_vpc_peer_req
に登録しました。
when
を使い、stdout
属性を参照しfalse
の場合のみ、こののタスクを実行します。
まとめ
AnsibleでAWSリソースを管理する場合に懸念点になる新機能サポートですが、commandモジュールからAWS CLIを叩くことで回避することができました。 本当はすべてモジュールで管理したいところですが、AWSの新機能リリースの状況を考慮すると、完璧に行うことは困難です。 とはいえ、構成管理で一部手動となることは、可能な限り避けたいところです。 うまくバランスをとりながら、AnsibleからAWS CLIを実行しましょう。