3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

kumogata2 を使用して、 AWS CloudFormation スタックを適用前に差分確認をする

Last updated at Posted at 2020-12-03

この記事は Akatsuki Advent Calendar 2020 4日目の記事です。
前回の記事は tomotaka-yamasaki さんの 開発エンジニアとQAの心理の違いとは何か? でした。

はじめに

私の所属するチームでは日々、安全な運用を継続しつつ運用業務改善を行っています。
今日はその中で AWS CloudFormation(以下Cfn) において、 kumogata2 を使った運用をご紹介します。

AWS CloudFormation とは

詳しくは AWS の公式ドキュメントをご確認ください。

Infrastructure as Code(以下IaC) を使用した、クラウドプロビジョニングサービスです。
スタックという単位で管理されており、スタックごと下記のようなyaml形式のテンプレートを作成して、 AWS リソースをコードで管理することができます。
1つのスタックで、VPC、AutoScaling、EC2の構成など複数サービスの依存関係を含めて表現することができます。

test.yml
AWSTemplateFormatVersion: '2010-09-09'
Description: Test Instance
Resources:
  TestInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-abcdexxxxxx
      InstanceType: t3.micro
      Tags:
      - Key: Name
        Value: test
      BlockDeviceMappings:
      - DeviceName: "/dev/xvda"
        Ebs:
          VolumeType: gp2
          VolumeSize: '32'

例)Cfn で EC2 インスタンスを作成する

メリット

  • 環境を複製できる
  • インフラの変更をレビューすることができる
  • ログを残して変更経緯を追うことができる
  • 手動によるオペレーションミス・漏れがなくなる

何年も運用していくと検証・開発環境への要望も変わってくることもありますが、そういった要望にも柔軟に対応することができます。
また、作成・削除を簡単に行えるため、テンポラリな環境を作成することにも役立ちます。

デメリット

強いてあげるとしたら

  • 変更に手間が増える

がありますが Cfn 管理していても一時的な変更であれば手動で変更して確認できたら元に戻せば良いので、あまりデメリットとは言えないかもしれません

kumogata2 とは

Cfn のスタックを作成することができるツールです。
特徴としては

  • Rubyでかける
  • Cfn スタックの作成・更新・削除を CLI で完結させられる
  • dry-run で依存関係を含めて更新箇所を確認することができる

でしょうか。

dry-run で依存関係を含めて更新箇所を確認することができる

依存関係がわかることによって、

「インスタンスのボリュームだけを変更するつもりが、インスタンスごと入れ替わってしまった」

といったことを事前に回避できます。

また、私のプロジェクトではkumogata2-plugin-rubyも合わせて使っています。

使い方

test.rb
TestInstance do
  Type "AWS::EC2::Instance"
  Properties do
    ImageId 'ami-abcdexxxxxx'
    InstanceType 't3.micro'
    Tags [
      _{
       Key "Name"
       Value "test"
      }
    ]
    BlockDeviceMappings [
    _{
      DeviceName "/dev/xvda"
      Ebs do
        VolumeType "gp2"
        VolumeSize '32'
      end
      }
    ]
  end
end

新規作成

このように書くことで最初に紹介した test.yml の形式に kumogata2 が変換してスタックを作成してくれます。

$ kumogata2 create test.rb test

を実行することによって、 Cfn 上に test というスタックが作成され、インスタンスが立ち上がります。

更新

また、スタックのVolumeSizeを 32 → 64に変更を行いたい際は
dry-runを実行することによって、更新する際に変更される差分のみ確認できます。

$ kumogata2 dry-run test.rb test
[
  {
    "Action": "Modify",
    "LogicalResourceId": "TestInstance",
    "PhysicalResourceId": "ami-abcdexxxxxx",
    "ResourceType": "AWS::EC2::Instance",
    "Details": [
      {
        "attribute": "Properties",
        "name": "BlockDeviceMappings"
      }
    ]
  }
]

困っていたこと

BlockDeviceMappings に変更が入るのみ

ということまでは確認できていたのですが、このままでは本当に 32 → 64 という変更が行われているのかがわかりません。

プロジェクトでは複数人が Cfn の管理を行っているので、適用時にBlockDeviceMappingsにはVolumeSize以外のパラメータもあるので、不要なものまで適用されてしまうかもしれません。

BlockDeviceMappings:
- DeviceName: "/dev/xvda"
  Ebs:
    VolumeType: gp2
    VolumeSize: '32'

そのため私のプロジェクトでは、

$ kumogata2 convert test.rb

でローカルで更新したいテンプレートフォーマットを作成したものと、
Cfn上のテンプレートを取得して、

変更差分がVolumeSizeのみであることを確認してから適用していました。

diffのコマンドがほしい

さすがに毎回確認をするのが大変だったので、diffコマンドを探しました。
Kumogata2 Usageにコマンド自体はあったのですが、そのまま適用するとパースでエラーになってしまったり、必要以上に機能があったのでプロジェクトに合わせて変更を加えました。

今回の要件としては、スタックの更新する際の差分が確認したい。

だったので
https://github.com/kumogata/kumogata2/blob/master/lib/kumogata2/client.rb
にオーバーライドする形で以下を追記しました。
また、Lambda や CloudWatch で日本語を使っていたのですが、 CloudFormation API がマルチバイトに対応していなかったため、diffを取る前に API の結果と同じになるようにコンバートしています。

kumogata2_patch.rb
def export_template(stack_name)
  stack = get_resource.stack(stack_name)
  stack.stack_status
  stack.client.get_template(stack_name: stack_name).template_body
end

def diff(path_or_url, stack_name)
  remote_stack = export_template(stack_name)
  local_stack = convert(path_or_url)
  # 現状CloudFormation APIがマルチバイト文字を?に変換してしまうため、同様の変換をかけてからdiffをとる
  File.write("/tmp/remote_stack.txt", remote_stack.gsub(/[^\x00-\x7f]/, '?'))
  File.write("/tmp/local_stack.txt", local_stack.gsub(/[^\x00-\x7f]/, '?'))
  system("diff -u /tmp/remote_stack.txt /tmp/local_stack.txt")
end

結果

$ kumogata2 diff test.rb test
       - DeviceName: "/dev/xvda"
         Ebs:
           VolumeType: gp2
-          VolumeSize: '32'
+          VolumeSize: '64'

これでVolumeSizeのみに差分があることを確認してから適用できるようになりました。

さいごに

今回差分を出せるようにしたことによって

  • 差分を見る手間が減った
  • 誰が差分確認しても同じ確認をできるようになった
    • 自動化/コマンド化されていない手動の運用は作業者によって手順が異なる可能性があります。
    • 差分を確認したつもりが手順を間違えていたため、きちんとした差分確認ができず不要な対応を適用してしまうことがなくなります。

が達成できました。
少人数で運用を回しつつ新しい挑戦をするにはこういった小さな改善が必要不可欠なので今後も続けていきたいと思います!

参考

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?