Test KitchenでAmazonLinuxのレシピ開発効率化2

前回の1回目の続きです。前回はTest KitchenでVagrantのCentOS上で環境の構築とテストまでやりましたので、今回は表題であるAmazonLinuxを使ってレシピをテストします。

kitchen-ec2を利用する

kitchen-ec2をインストールします。

$ gem install kitchen-ec2

kitchen-ec2を実行するIAMユーザーを作成する

AWSのIAMの管理コンソールからtest-kitchenというユーザーを作成します。アクセスキーとシークレットはメモしておきます。

作成したユーザーのアクセス許可で下記のようなIAMポリシーを設定します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "ec2:*",
            "Effect": "Allow",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "sts:DecodeAuthorizationMessage",
            "Resource": "*"
        },
        {
            "Effect": "Deny",
            "Action": [
                "ec2:RunInstances"
            ],
            "Condition": {
                "StringNotEquals": {
                    "ec2:InstanceType": [
                        "t1.micro",
                        "m1.small"
                    ]
                }
            },
            "Resource": [
                "arn:aws:ec2:*:アカウント番号:instance/*"
            ]
        }
    ]
}

kitchen-ec2で利用するセキュリティグループを用意する

AWSのEC2の管理コンソールの中で下記のようなセキュリティグループを用意します。

NewImage

NewImage

kitchen-ec2で利用するキーペアを用意する

何でも構いませんのでキーペアを作成しTest Kitchenを実行するローカルマシンの~/.ssh/配下に保存しておきます。

kitchen-ec2用に.kitchen.ec2.ymlを作成する

ファイル名は何でも大丈夫なんですが、どうもTest Kitchenは複数のドライバを混在させる事ができないため前回定義したkitchen-vagrant用の.kitchen.ymlとは別にkitchen-c2用の.kitchen.ymlを作成する必要があります。今回は分かりやすさのために.kitchen.ec2.ymlとしておきます。

security_group_idsは先程用意したセキュリティグループのIDを指定します。レシピの内容は適当に読み替えて下さい。

.kitchen.ec2.yml

---
driver:
  name: ec2
  region: ap-northeast-1
  availability_zone: ap-northeast-1a

provisioner:
  name: chef_solo

platforms:
  - name: amzn-201509
    driver:
      image_id: ami-393c1957
      instance_type: t1.micro
      security_group_ids: ["sg-xxxx"]
    transport:
      username: ec2-user
      ssh_key: "~/.ssh/<%= ENV['AWS_SSH_KEY_ID'] %>.pem"

suites:
  - name: default
    run_list:
      - recipe[nginx::default]
    attributes: {
      nginx: {
        root: "/var/www/html",
        conf:  "fpm-default.conf",
        ssl: {
          key: "-----BEGIN RSA PRIVATE KEY-----...",
          cert: "-----BEGIN CERTIFICATE-----..."
        }
      }

なお、kitchen-ec2のデフォルトのインスタンスタイプはm1.smallです。現在のGitHubのマスターがt2.microになってるので将来は変わるとは思います。現在gemで入手できるバージョンだとt2.microはエラーが出てうまくいかないため変わりにt1.microを利用することができます。

次にexport.shという名前で下記のファイルを作成します。

export KITCHEN_YAML=.kitchen.ec2.yml
export AWS_ACCESS_KEY_ID=test-kitchenユーザーのアクセスキー
export AWS_SECRET_ACCESS_KEY=test-kitchenユーザーのシークレット
export AWS_SSH_KEY_ID=キーペアの名称

Test KitchenをEC2上で実行する

$ source export.sh
$ kitchen create

無事作成できました。

$ kitchen list
Instance             Driver  Provisioner  Verifier  Transport  Last Action
default-amzn-201509  Ec2     ChefSolo     Busser    Ssh        Created

次にkitchen verifyします。

$ kitchen verify
       ...
       Package "nginx"
         should be installed
       
       Service "nginx"
         should be enabled
         should be running
       
       Port "80"
         should be listening
       
       File "/etc/nginx/nginx.conf"
         should be file
         should contain "off;"
       
       File "/etc/nginx/conf.d/default.conf"
         should be file
         should contain "unix:/var/run/php-fpm/php-fpm.sock;"
       
       Finished in 0.3826 seconds (files took 0.53725 seconds to load)
       8 examples, 0 failures
       
       Finished verifying <default-amzn-201509> (0m18.42s).

うまくテストも通りました。

確認できたら早々にインスタンスを破棄しておきます。

$ kitchen destroy

CentOSとAmazonLinuxで同時に実行する

Test Kitchenには--concurrencyという複数同時実行のオプションがあります。これを使って前回のVagrantのCentOSと今回のkitchen-ec2のAmazonLinuxを同時に実行できればレシピ開発の手間を削減できるなと考えました。ですが、これは残念ながらTest Kitchenの制限で出来ないようでした。

どうも複数のドライバを同時に利用するようには今のところ考えられていないようです。なので、やるのであればやや富豪的考え方になりますがEC2でCentOSのインスタンスも同時にテストする形になります。t1.microで実行すれば無料枠内に収まりますし、m1.smallでもテスト実行だけ定期的に行うだけであれば最小の1時間の課金で$0.061なので消し忘れなければ大した事ないです。

旧世代のインスタンス

コミュニティAMIのCentOSを利用する

CentOSのコミュニティAMIの利用できるようにするためにEC2の管理コンソールから一旦コミュニティIDでEC2インスタンスを起動します。ステップ1のAMIの選択画面でコミュニティAMIを選択し「CentOS-6.5 GA」で検索しIDがami-81294380のものを選択します。なおkitchen-ec2は今のところ仮想化タイプがparavirtualのもので動作するようです。

すると下記のように失敗すると思います。

NewImage

エラーメッセージを読むとAMIを利用する前に条項に同意する必要があるという事で、案内されている下記のURLへ移動します。

http://aws.amazon.com/marketplace/pp?sku=eggbgx9svw4xhzs1omttdv29q

NewImage

RegionをTokyoにして「Continue」します。

NewImage

このページで「Accept Terms & Launch with 1-Click」をクリックしてインスタンスを起動します。EC2の管理コンソールでインスタンスが起動中になっていればコミュニティAMIを利用する準備は完了しています。

同時にレシピを実行する

.kitchen.ec2.ymlを下記のように修正します。

platforms:
  - name: amzn-201509
    driver:
      image_id: ami-393c1957
      instance_type: t1.micro
      security_group_ids: ["sg-xxxx"]
    transport:
      username: ec2-user
      ssh_key: "~/.ssh/<%= ENV['AWS_SSH_KEY_ID'] %>.pem"

  - name: centos-6.5
    driver:
      image_id: ami-81294380
      instance_type: t1.micro
      security_group_ids: ["sg-xxxx"]
    transport:
      username: root
      ssh_key: "~/.ssh/<%= ENV['AWS_SSH_KEY_ID'] %>.pem"

kitchen listで確認すると2つインスタンスがありどちらもNot Createdになっていると思います。

$ kitchen list
Instance             Driver  Provisioner  Verifier  Transport  Last Action
default-amzn-201509  Ec2     ChefSolo     Busser    Ssh        <Not Created>
default-centos-65    Ec2     ChefSolo     Busser    Ssh        <Not Created>

kitchen testを複数同時に実行する–concurrency(あるいは-c)オプションをつけて実行してみましょう。kitchen testは一気にインスタンス起動からレシピ実行・テストまでを行うコマンドです。

$ kitchen test -c 2

無事2つ同時にテストが完了しました。インスタンスも綺麗に消えてくれています。

$ kitchen list
Instance             Driver  Provisioner  Verifier  Transport  Last Action
default-amzn-201509  Ec2     ChefSolo     Busser    Ssh        <Not Created>
default-centos-65    Ec2     ChefSolo     Busser    Ssh        <Not Created>

CentOSとAmazonLinuxを同時に開発しながらkitchen convergekitchen verifyで検証しながら進めてもいいですし、あるいは実装済みのレシピを修正した際にAmazonLinuxでの検証を1コマンドで済ませるためにkitchen testで確認するという使い方もできると思います。

以上で2回に分けましたがAmazonLinuxのレシピ開発効率化でした。