前回は Piculet を使ってセキュリティグループ設定と Groupfile の比較を CircleCI でチェックできるところまで試した.興味があったら是非以下の記事を見てもらえると!
今回は前回の続きで,主に --apply
オプションを使った反映を試してみた.最後に Piculet を運用に活用するならどんなフローになるか?を考えてみた.
新規セキュリティグループを反映してみる
まず,以下のような Groupfile を用意した."dev-web" という名前のセキュリティグループで,特定の IP アドレス(今回は 1.2.3.4)から http アクセスを許可する設定にしている.
# -*- mode: ruby -*- # vi: set ft=ruby : ec2 "vpc-xxxxxxxx" do security_group "dev-web" do description "web for dev env" ingress do permission :tcp, 80..80 do ip_ranges( "1.2.3.4/32" ) end end egress do permission :any do ip_ranges( "0.0.0.0/0" ) end end end end
反映する前に --apply
オプションと合わせて使える --dry-run
オプションを使って検証をしてみた.ちなみに --dry-run
オプションは Piculet 独自のオプションではなくて AWS SDK for Ruby の API で用意されたオプションだ.以下のように意図した通りにセキュリティグループが反映されるようなログが出力された.
$ piculet --apply --dry-run --names dev-web Apply `Groupfile` to SecurityGroup (dry-run) Create SecurityGroup: vpc-xxxxxxxx > dev-web (dry-run) Create Permission: vpc-xxxxxxxx > dev-web(ingress) > tcp 80..80 (dry-run) authorize 1.2.3.4/32 (dry-run) No change
次に実際に反映してみた.成功!
$ piculet --apply --names dev-web Apply `Groupfile` to SecurityGroup Create SecurityGroup: vpc-xxxxxxxx > dev-web Create Permission: vpc-xxxxxxxx > dev-web(ingress) > tcp 80..80 authorize 1.2.3.4/32
正しく反映されていた.
ちなみに Piculet では冪等性の考慮がされていて,全く同じ DSL であれば何度反映してもスキップとなる.ただし,後述する通り,グループ名とグループ説明を修正する場合は新規作成となるため,注意が必要になる.
$ piculet --apply --names dev-web Apply `Groupfile` to SecurityGroup No change
ルールを変更してみる
次に Groupfile を修正して 80
→ 443
にして反映してみた.
# -*- mode: ruby -*- # vi: set ft=ruby : ec2 "vpc-xxxxxxxx" do security_group "dev-web" do description "web for dev env" ingress do permission :tcp, 443..443 do ip_ranges( "1.2.3.4/32" ) end end egress do permission :any do ip_ranges( "0.0.0.0/0" ) end end end end
既存ルール 80
は削除されて,新規ルール 443
が反映された.グループ ID は同じで,副作用なく反映できていた.
$ piculet --apply --dry-run --names dev-web Apply `Groupfile` to SecurityGroup (dry-run) Delete Permission: vpc-xxxxxxxx > dev-web(ingress) > tcp 80..80 (dry-run) revoke 1.2.3.4/32 (dry-run) Create Permission: vpc-xxxxxxxx > dev-web(ingress) > tcp 443..443 (dry-run) authorize 1.2.3.4/32 (dry-run) No change $ piculet --apply --names dev-web Apply `Groupfile` to SecurityGroup Delete Permission: vpc-xxxxxxxx > dev-web(ingress) > tcp 80..80 revoke 1.2.3.4/32 Create Permission: vpc-xxxxxxxx > dev-web(ingress) > tcp 443..443 authorize 1.2.3.4/32
ingress にグループ名を指定してみる
次に groups
を使ってグループ名を指定してみる.ちなみに default
は存在するグループ名で,known_group
は存在しないグループ名とした.
# -*- mode: ruby -*- # vi: set ft=ruby : ec2 "vpc-xxxxxxxx" do security_group "dev-web" do description "web for dev env" ingress do permission :tcp, 443..443 do groups( "default", "known_group" ) end end egress do permission :any do ip_ranges( "0.0.0.0/0" ) end end end end
恐らく AWS SDK for Ruby の仕様(バグ?)だとは思うが,存在しないグループ名を指定しても --dry-run
だと検知できなかった.よって,実際に反映する際にエラーになってしまった.--dry-run
で検知できれば良いのに...!
あと1点気になったのは,複数のセキュリティグループを一括で反映するときに一部にエラーが発生しても,全体をロールバックする機能はないということ.ようするにエラーが発生するまでの反映はそのまま apply されてしまう.CloudFormation とは違うという認識を持っておく必要がありそう.
$ piculet --apply --dry-run --names dev-web Apply `Groupfile` to SecurityGroup (dry-run) Update Permission: vpc-xxxxxxxx > dev-web(ingress) > tcp 443..443 (dry-run) authorize default, known_group (dry-run) revoke 1.2.3.4/32 (dry-run) No change $ piculet --apply --names dev-web Apply `Groupfile` to SecurityGroup Update Permission: vpc-xxxxxxxx > dev-web(ingress) > tcp 443..443 authorize default, known_group [ERROR] Can't find SecurityGroup: 111111111111/known_group in vpc-xxxxxxxx
テンプレート機能
Piculet にはテンプレート機能があり,共通の DSL を定義しておいて,再利用することができる.管理コンソールでセキュリティグループを管理するときにツライと感じるのは IP アドレスに別名(コメント)を付与することができないところで,特に複数オフィスの IP アドレスを登録しているとパッと見で判断できなくなる.テンプレートにコメントを書いて GitHub で管理しておけば,運用的に助かるし便利機能だと思った.以下のように書ける.
# -*- mode: ruby -*- # vi: set ft=ruby : template "https_from_office" do permission :tcp, 443..443 do ip_ranges( "1.2.3.4/32" ) end end ec2 "vpc-xxxxxxxx" do security_group "dev-web" do description "web for dev env" ingress do include_template "https_from_office" end egress do permission :any do ip_ranges( "0.0.0.0/0" ) end end end end
ただし,テンプレート機能を使う場合,Groupfile をマスタとして管理していく必要がある.もし一時的に管理コンソールで直接修正をして,もう一度 Piculet でエクスポートをするとテンプレートは消えてそのまま展開されてしまう.運用フロー次第かなと.
グループ名とグループ説明を変更してみる(冪等性が保証されない)
web
を web2
に修正して反映してみる.
# -*- mode: ruby -*- # vi: set ft=ruby : template "https_from_office" do permission :tcp, 443..443 do ip_ranges( "1.2.3.4/32" ) end end ec2 "vpc-xxxxxxxx" do security_group "dev-web2" do description "web2 for dev env" ingress do include_template "https_from_office" end egress do permission :any do ip_ranges( "0.0.0.0/0" ) end end end end
まず,既存の dev-web
セキュリティグループを EC2 に紐付けた状態にした.
$ aws ec2 describe-instances --instance-ids i-xxxxxxxx | jq '.Reservations[].Instances[].SecurityGroups' [ { "GroupName": "dev-web", "GroupId": "sg-11111111" } ]
すると,ルールは全て削除されてしまった.ただし,セキュリティグループ自体は [ERROR] resource sg-11111111 has a dependent object
のエラーが出て削除されなかった.インスタンスに紐付いている場合,セキュリティグループは残るものの,ルールは全て消えてしまうため,意図的に反映しないと大規模障害の引き金となってしまいそう.
$ piculet --apply --dry-run --names dev-web Apply `Groupfile` to SecurityGroup (dry-run) Delete Permission: vpc-xxxxxxxx > dev-web(ingress) > tcp 443..443 (dry-run) revoke 1.2.3.4/32 (dry-run) Delete Permission: vpc-xxxxxxxx > dev-web(egress) > any (dry-run) revoke 0.0.0.0/0 (dry-run) Delete SecurityGroup: vpc-xxxxxxxx > dev-web (dry-run) No change $ piculet --apply --names dev-web Apply `Groupfile` to SecurityGroup Delete Permission: vpc-xxxxxxxx > dev-web(ingress) > tcp 443..443 revoke 1.2.3.4/32 Delete Permission: vpc-xxxxxxxx > dev-web(egress) > any revoke 0.0.0.0/0 Delete SecurityGroup: vpc-xxxxxxxx > dev-web [ERROR] resource sg-11111111 has a dependent object
またグループ説明だけを修正した場合はエラーになる.これは良かった.グループ説明だけを修正した場合に新規セキュリティグループが反映されたら障害になってしまうし.
$ piculet --apply --dry-run --names dev-web Apply `Groupfile` to SecurityGroup (dry-run) [WARN] `description` cannot be updated: vpc-xxxxxxxx > dev-web (dry-run) No change $ piculet --apply --names dev-web Apply `Groupfile` to SecurityGroup [WARN] `description` cannot be updated: vpc-xxxxxxxx > dev-web No change
運用を考えた
Piculet を活用する運用フローを考えてみた.ただし EC2 や RDS の運用を自動化してるかどうかによっても大きく違うと思うので,あくまで参考まで.
案1. 管理コンソールでの反映を禁止し,全て Piculet を使う場合
基本的に運用メリットが大きいフローだと思う.ただし,既に本番稼働中のサービスに導入するには Piculet の仕様をちゃんと理解して,適切に活用する必要がある.
- メリット
- 全ての運用を自動化できる(CircleCI で master にマージされたら反映したり)
- プルリクベースで反映内容を事前にレビューできる
- Piculet のテンプレート機能が使える
- 新規プロジェクトに導入し易い
- 新規プロジェクトなら部分最適 < 全体最適 だから CloudFormation / Terraform の方が良いかも
- デメリット
- 一時的に管理コンソールで変更をしてしまうと簡単に Groupfile との差が生じてしまう
- 変更を検知できる別の仕組みが必要そう
- 一時的に管理コンソールで変更をしてしまうと簡単に Groupfile との差が生じてしまう
案2. 管理コンソールでの反映を許容し,部分的に Piculet で反映する場合
- メリット
- Piculet で反映する場合は
--names
オプションを指定して部分的に反映できる - 管理コンソールでの反映も許容することである程度自由度を残した運用が可能になる
- 管理コンソールで反映した場合はすぐに Groupfile をエクスポートして GitHub を最新にする必要がある
- 前回試した CircleCI で CI するフローを徹底する必要がある
- 本番稼働中のサービスに導入し易い
- Piculet で反映する場合は
- デメリット
- 反映を完全に自動化できないため,運用カバーな部分が残ってしまう
- Groupfile の運用が暗黙知になってインフラ担当が権威的になってしまう可能性がありそう
案3. 全ての反映を管理コンソールで実施し,常に最新の Groupfile を GitHub でバージョン管理する
- メリット
- 管理コンソールを使っていた場合に,今までの運用を大きく変えずにセキュリティグループ設定をバージョン管理できる
- 前回試した CircleCI で CI するフローを徹底することで差分を検知することができる
- 本番稼働中のサービスに導入し易い
- デメリット
- 自動化とは程遠い運用になってしまう
まとめ
前回 と今回で Piculet を一通り試した.とにかく素晴らしい!ただ前回も書いた通り,もう少し README が充実してると導入し易いとは思う.特に反映時の冪等性のあたりなど,仕様を理解しておかないと不安な部分だしなーとは思った.
ちなみに僕が担当してる現場の話で言うと,現在はまだセキュリティグループの運用を全て管理コンソールで行っていて,管理面に課題を感じていた(だからこそ今回 Piculet を試していた).現実的に今回考えた「案2」or「案3」になりそうだけど,提案してみようと思う.
同時に Piculet を運用で使ってる人の話を聞いてみたいと思ってて,タイミング良く 12/08 に Codenize Meetup が開催される!絶対参加したいし抽選に当たることを祈ってる...!!!