funasaki memo

このブログ上の投稿は個人のものであり、所属する企業を代表する投稿ではありません。所属:AWSのSolutions Architect

aws-cliを使ってAutoScaling Groupを作成してみる。

launch-configurationを作成

$ aws autoscaling create-launch-configuration --launch-configuration-name config1 --image-id ami-39b23d38 --instance-type t1.micro --key-name ap-northeast

作成結果を確認

$ aws autoscaling describe-launch-configurations --output text

        ap-northeast    arn:aws:autoscaling:ap-northeast-1:XXXXXXXXXXXX:launchConfiguration:0ad52a06-34d4-4c70-940c-b4b5a23adbd9:launchConfigurationName/config1        ami-39b23d38            False   config1 2013-08-23T10:44:36.777Z                t1.micro
INSTANCEMONITORING      True
RESPONSEMETADATA        5d980e12-0be1-11e3-a812-5b0041b22e4e

auto-scaling-groupを作成

$ aws autoscaling create-auto-scaling-group --auto-scaling-group-name group1 --launch-configuration-name config1 --min-size 2 --max-size 2 --vpc-zone-identifier subnet-d8de6cb0,subnet-96d96bfe

作成結果の確認

$ aws autoscaling describe-auto-scaling-groups --output text

arn:aws:autoscaling:ap-northeast-1:XXXXXXXXXXXXXX:autoScalingGroup:3cffd102-8a3e-4756-8a20-3343b39ba977:autoScalingGroupName/group1       0       2       group1  300     2       2       subnet-d8de6cb0,subnet-96d96bfe config1 2013-08-23T10:58:55.700Z        EC2
i-02215307      ap-northeast-1c Healthy InService       config1
i-9fe2059a      ap-northeast-1a Healthy InService       config1
RESPONSEMETADATA        45062903-0be3-11e3-84d9-670da55b233a

インスタンス2つが、異なるサブネット(異なるAZ)で起動しているのが分かりますね。

ついでに削除処理もメモとして残しておきます。

$ aws autoscaling update-auto-scaling-group --auto-scaling-group-name group1 --min-size 0 --max-size 0
$ aws autoscaling delete-auto-scaling-group --auto-scaling-group-name group1
$ aws autoscaling delete-launch-configuration --launch-configuration-name config1
以上で削除完了です。AutoScaling groupの削除は、インスタンスが完全にterminateされてからでないと削除はできませんので、ご注意を。

Amazon Linux 2013.03にデフォルトでインストールされているAWS CLIにhelpが入ってない。

https://forums.aws.amazon.com/thread.jspa?messageID=449307
こちらのディスカッションフォーラムにもあるように、Amazon Linux 2013.03にはaws-cliのhelp(manual entry)が入っていないです。

$ aws --version
aws-cli/0.9.3 Python/2.6.8 Linux/3.4.43-43.43.amzn1.x86_64

以下のようにhelpコマンドを実行しても表示されません。

$ aws help
No manual entry for aws

ので、aws-cliを一旦削除して再インストールし直すことにしました。

$ sudo yum remove  aws-cli
$ sudo yum -y update
$ sudo easy_install pip
$ sudo pip install awscli

インストール後、helpを実行すると、

$ aws help
AWS()                                                                    AWS()



NAME
       aws -

DESCRIPTION
       The  AWS  Command Line Interface is a unified tool that provides a con-
       sistent interface for interacting with all parts of AWS.

SYNOPSIS
           aws [options] <service_name> <operation> [parameters]

       Use aws service help for information on a specific service.

OPTIONS
       --debug (boolean)

       Turn on debug logging.

       --endpoint-url (string)

正しく表示されました。よかったよかった。
ちなみに新しく入れたaws-cliのバージョンは

$ aws --version
aws-cli/0.14.1 Python/2.6.8 Linux/3.4.43-43.43.amzn1.x86_64

元々入っていたのが0.9.3だったので、元々のは結構古かったみたいですね。

AWS CLIを使ってTagの値のみを取得する

AWS CLIを使って、以下のように割り当てられたインスタンスのTagの値のみ(今回はWordPress)を取得します。
f:id:kenjifunasaki:20130814155254p:plain
今回はAmazon Linuxを使うので、AWS CLIのインストール方法は割愛します。

# Amazon Linux 2013.03に入っているデフォルトのaws-cliを使いました。バージョンは以下です。

$ aws --version
aws-cli/0.9.3 Python/2.6.8 Linux/3.4.43-43.43.amzn1.x86_64

#バージョンが異なると、オプションの指定が異なる可能性があります。

まず以下の環境変数を設定します。

export AWS_DEFAULT_REGION=ap-northeast-1
export AWS_CREDENTIAL_FILE=/opt/aws/credential-file

credential-fileを作成します。

$ sudo cp /opt/aws/credential-file-path /opt/aws/credential-file
$ sudo vi /opt/aws/credential-file
AWSAccessKeyId=XXXXXXXXXXXXXXXXXX
AWSSecretKey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

以下コマンドを実行して動作確認。

$ aws ec2 describe-instances
{
    "Reservations": [
        {
            "OwnerId": "000000000000",
            "ReservationId": "r-883ce98b",
            "Groups": [
(以下省略)

ちゃんと出力されることを確認。

$ aws ec2 describe-tags
{
    "ResponseMetadata": {
        "RequestId": "b98ff86b-24e7-4950-9161-c864e11c20a7"
    },
    "Tags": [
        {
            "ResourceType": "snapshot",
            "ResourceId": "snap-6d0d4c4d",
            "Key": "Name",
            "Value": "dev-urandom-1G"
        },
        {
            "ResourceType": "security-group",
            "ResourceId": "sg-958dff94",
            "Key": "aws:cloudformation:stack-name",
            "Value": "WordpressSite"
        },
(以下省略)

通常describe-tagsを実行すると、全部のTagが出てきてしまうので、絞り込みをします。

$ aws ec2 describe-tags --filter '{"name":"resource-id","values":"i-06672203"}'
{
    "ResponseMetadata": {
        "RequestId": "8c60bc2e-16bc-4882-8bfb-de5889eb84c3"
    },
    "Tags": [
        {
            "ResourceType": "instance",
            "ResourceId": "i-06672203",
            "Key": "Name",
            "Value": "WordPress"
        }
    ]
}

これをさらに絞り込むためにjqを使います。jqは入力内容を元に出力を絞り込むためのプログラムです。
まずは、jqをインストール。

$ sudo yum install jq

そして、上記出力をjqを使って絞り込みます。

$aws ec2 describe-tags --filter '{"name":"resource-id","values":"i-06672203"}' | jq '.Tags[] | .Value'
"WordPress"

以上で、WordPressの値のみを抽出することができました!

もちろん、Name以外のTagも取得できますので、いろいろ使いまわせそうですね。

AWS Security Token Serviceを使ってみる

AWS SDKやAWSコマンドラインツールを使う場合、Security Credentialsが必要になります。Security Credentialsの中にはアクセスキーとシークレットアクセスキーが含まれています。AWSのサービスやリソースをAPIを使って管理するときには、この2つのキーを使って認証します。

この2つのキーをどうやって保管するか?が本記事の目標とするところです。

2つのキーをソースコードやもしくはテキストファイル、DB等に格納して使うこともできますが、これだとキーの置き換えをするのが大変です。そこでAWSから提供されているSecurity Token Serviceというサービスを使って、キーの管理を安全に、かつ効率的に行うことを試してみました。

Security Token Serviceとは?
一時的な、かつ制限された特権を持つAWSアカウント、またはIAMユーザのCredential情報を取得可能にする機能です。Security Token Serviceは、以下の3つのアクションが可能です。

AWS SDKでSecurity Token Serviceより権限を取得できる。対応しているSDKは2013/04/16時点では以下。

http://docs.aws.amazon.com/STS/latest/UsingSTS/AccessingSTS.html

AWS SDK for Javaを使って、GetSessionTokenした例が以下。今回は取得した権限でS3のバケットリストを表示させている。

import java.io.IOException;
import java.util.List;

import com.amazonaws.AmazonWebServiceClient;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.auth.BasicSessionCredentials;
import com.amazonaws.auth.PropertiesCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient;
import com.amazonaws.services.securitytoken.model.Credentials;
import com.amazonaws.services.securitytoken.model.GetSessionTokenRequest;
import com.amazonaws.services.securitytoken.model.GetSessionTokenResult;


public class MySecurityTokenSample {

	public static void main(String[] args) throws IOException {
		
		//STSからトークンを取得するために必要なCredential情報
		AWSCredentials credentials = new PropertiesCredentials(
                MySecurityTokenSample.class.getResourceAsStream("AwsCredentials.properties"));
		
		//SecurityTokenServiceClientの設定
		AWSSecurityTokenServiceClient sts = new AWSSecurityTokenServiceClient(credentials);
		GetSessionTokenRequest req = new GetSessionTokenRequest();
		GetSessionTokenResult res = sts.getSessionToken(req);
		Credentials tmpCredentials = res.getCredentials();
		String accessKeyId = tmpCredentials.getAccessKeyId();
		String secretAccessKeyId = tmpCredentials.getSecretAccessKey();

		//取得したアクセスキー、シークレットアクセスキーでS3のバケットリストを表示してみる。
		BasicSessionCredentials c = new BasicSessionCredentials(tmpCredentials.getAccessKeyId(),
				tmpCredentials.getSecretAccessKey(), tmpCredentials.getSessionToken());
		AmazonS3Client s3Client = new AmazonS3Client(c);
		s3Client.setEndpoint("s3-ap-northeast-1.amazonaws.com");
					
		List<Bucket> list = s3Client.listBuckets();
		for(Bucket b : list) {
			System.out.println(b.getName());
		}
	}
}

こちらを実行すると、バケット名のリストが表示された。
トークンを取得するためには、やはりSecurity Credentialsの情報が必要。なので、システムの中に1台だけトークン管理サーバなるものを立てて、そこの中では唯一Credentials情報を持つ。他のサーバで一時的にCredentials情報が必要な場合は、このサーバが何かしらの安全な方法で配ってあげる形が良さそう。取得したトークンは、デフォルトで12時間まで有効。その時間が過ぎると無効になる。以下のように実行することで、その時間も変更できる。

getSessionTokenRequest.setDurationSeconds(7200); 

上記例では、AWSアカウントの権限を取得していたが、以下のようにgetFederatedTokenを使って指定したIAM Userの権限を取得もできる。

import java.io.IOException;
import java.util.List;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.auth.BasicSessionCredentials;
import com.amazonaws.auth.PropertiesCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient;
import com.amazonaws.services.securitytoken.model.Credentials;
import com.amazonaws.services.securitytoken.model.GetFederationTokenRequest;
import com.amazonaws.services.securitytoken.model.GetFederationTokenResult;
import com.amazonaws.services.securitytoken.model.GetSessionTokenRequest;
import com.amazonaws.services.securitytoken.model.GetSessionTokenResult;


public class MySecurityTokenSample2 {

public static void main(String[] args) throws IOException {
		
		//STSからトークンを取得するために必要なCredential情報
		AWSCredentials credentials = new PropertiesCredentials(
                MySecurityTokenSample.class.getResourceAsStream("AwsCredentials.properties"));
		
		//SecurityTokenServiceClientの設定
		AWSSecurityTokenServiceClient sts = new AWSSecurityTokenServiceClient(credentials);
		GetFederationTokenRequest req = new GetFederationTokenRequest();
		req.setName("TVMUser1");
		req.setPolicy("{\"Statement\": [{\"Effect\": \"Allow\",\"Action\": \"s3:*\",\"Resource\": \"*\"}]}");
		GetFederationTokenResult res = sts.getFederationToken(req);
		Credentials tmpCredentials = res.getCredentials();
		
		//取得したアクセスキー、シークレットアクセスキーでS3のバケットリストを表示してみる。
		BasicSessionCredentials c = new BasicSessionCredentials(tmpCredentials.getAccessKeyId(), 
				tmpCredentials.getSecretAccessKey(), tmpCredentials.getSessionToken());
		AmazonS3Client s3Client = new AmazonS3Client(c);
		s3Client.setEndpoint("s3-ap-northeast-1.amazonaws.com");
					
		List<Bucket> list = s3Client.listBuckets();
		for(Bucket b : list) {
			System.out.println(b.getName());
		}
	}
}

TVMUser1というIAM Userで、S3のみにアクセス可能なポリシーをJSONで書いたものを使ってGetFederationTokenしている。
req.setPolicyでは以下のJSONデータを引数に入れている。

{
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "*"
    }
  ]
}

このように、Security Token Serviceを使えば、一時的なCredentials情報を取得できることがわかった!

リンク

DynamoDBでscanを実行してみる

DynamoDBのテーブル名が SampleTable, AttributeがIdとNameのみのテーブルに対してScanを実行した。

AWS SDK for Javaで以下のように実行してみた。

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.PropertiesCredentials;
import com.amazonaws.services.dynamodb.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodb.model.AttributeValue;
import com.amazonaws.services.dynamodb.model.ComparisonOperator;
import com.amazonaws.services.dynamodb.model.Condition;
import com.amazonaws.services.dynamodb.model.GetItemRequest;
import com.amazonaws.services.dynamodb.model.GetItemResult;
import com.amazonaws.services.dynamodb.model.Key;
import com.amazonaws.services.dynamodb.model.PutItemRequest;
import com.amazonaws.services.dynamodb.model.PutItemResult;
import com.amazonaws.services.dynamodb.model.ScanRequest;
import com.amazonaws.services.dynamodb.model.ScanResult;


public class DynamoDBLoadGenerator {

	static AmazonDynamoDBClient dynamoDB;
	
	public static void main(String[] args) throws IOException {
		//Credentialsの設定
		AWSCredentials credentials = new PropertiesCredentials(
                DynamoDBSample.class.getResourceAsStream("AwsCredentials.properties"));

		//リクエストのパラメータの設定
                dynamoDB = new AmazonDynamoDBClient(credentials);
                dynamoDB.setEndpoint("http://dynamodb.ap-northeast-1.amazonaws.com");
                String tableName = "SampleTable";
        
         

                //ScanFilterConditionの設定
                Condition scanFilterCondition = new Condition()
    	               .withComparisonOperator(ComparisonOperator.LT.toString())   //〇〇よりも小さい
    	               .withAttributeValueList(new AttributeValue().withN("500")); //500
        
                Map<String, Condition> conditions = new HashMap<String, Condition>();
                conditions.put("Id", scanFilterCondition);
        
    	        ScanRequest scanRequest = new ScanRequest()
    		       .withTableName(tableName)
    		       .withScanFilter(conditions)
    		       .withAttributesToGet(Arrays.asList("Id")); //Idに対してScanFilterを実行

    	       //Scan実行
    	       ScanResult scanResult = dynamoDB.scan(scanRequest);
    
               //結果表示
               for (Map<String, AttributeValue> item : scanResult.getItems()){
        	     System.out.println(item.get("Id"));
               }
	}
}

実行結果は以下のように出力される。

{N: 251, }
{N: 187, }
{N: 154, }
{N: 7, }
{N: 115, }
{N: 286, }
{N: 361, }
{N: 380, }
{N: 117, }
{N: 401, }
{N: 47, }
{N: 184, }
{N: 403, }
{N: 304, }
{N: 156, }
{N: 122, }
{N: 273, }
以下省略

IDが500以下のデータが出力された。
また今回使用したScanFilterConditionでComparisonOperatorで、BETWEENやBEGIN WITHやCONTAINなどいろいろ指定できる。今回使ったのはLT(おそらくはLess Thanのことだと思う)。これでscanするフィルターをいろいろ設定できそう。

試しにNameが"Book 500"とイコールであるIdをFilterConditionで指定したのが以下。

        //ScanFilterConditionの設定
        Condition scanFilterCondition = new Condition()
    	.withComparisonOperator(ComparisonOperator.EQ.toString())
    	.withAttributeValueList(new AttributeValue().withS("Book 500"));


以下はComparisonOperatorのJavaDoc
[http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodb/model/ComparisonOperator.html:title=
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodb/model/ComparisonOperator.html]

AWS OpsWorksで起動されたインスタンスの中身を見てみる

AWS OpsWorksを使ってHAProxyのレイヤーを追加し、HAProxyインスタンスを立ち上げてみる。

自分のkeypairを使うように設定すれば、SSHでログインすることができる。

早速ログインしてみる。
ec2-userでログインができた。

OpsWorksの動作に関連しそうなものは以下のディレクトリにあった。

[ec2-user@stratus aws]$ sudo ls opsworks/current/bin
chef-client               gli             opsworks-agent-cli        restclient
chef-solo                 knife           opsworks-agent-installer  s3curl.pl
convert_to_should_syntax  lockrun         opsworks-agent-updater    shef
edit_json.rb              nokogiri        prettify_json.rb          thor
erubis                    ohai            rake
extract                   opsworks-agent  rake2thor

chef-soloやchef-client, opsworks-agent-cliなどがある。
AWSのドキュメントには、それぞれのインスタンスでchef-soloが動いていると書かれていた。
以下抜粋

Here's how it works: Chef Solo runs on every instance, and AWS OpsWorks sends commands to each instance to run recipes that set up, configure, and shut down the instance. You can extend these actions with your own custom recipes. You can also run your custom recipes on a specific instance or on all instances in your stack. 

さらにopsworks-agent-cliで以下のようなコマンドも実行できる。

  • agent_report
  • get_json
  • instance_report
  • list_commands
  • run_command
  • show_log
  • stack_state

詳細は以下。
http://docs.aws.amazon.com/opsworks/latest/userguide/agent.html

試しにget_jsonコマンドを実行してみた。(環境をまるさらしだが、すぐ消すので良しとしよう。。)

$ sudo opsworks/current/bin/opsworks-agent-cli get_json
{
  "recipes": [
    "opsworks_custom_cookbooks::load",
    "opsworks_ganglia::configure-client",
    "ssh_users",
    "agent_version",
    "haproxy::configure",
    "opsworks_stack_state_sync",
    "opsworks_custom_cookbooks::execute",
    "test_suite",
    "opsworks_cleanup"
  ],
  "opsworks_bundler": {
    "version": "1.0.10",
    "manage_package": null
  },
  "opsworks_rubygems": {
    "version": "1.8.24"
  },
  "opsworks": {
    "deployment": null,
    "valid_client_activities": [
      "reboot",
      "stop",
      "setup",
      "configure",
      "update_dependencies",
      "install_dependencies",
      "update_custom_cookbooks",
      "execute_recipes"
    ],
    "applications": [
      {
        "application_type": "php",
        "slug_name": "php_app",
        "name": "php-app"
      }
    ],
    "ruby_version": "1.8.7",
    "activity": "configure",
    "ruby_stack": "ruby_enterprise",
    "stack": {
      "name": "SampleStack3"
    },
    "instance": {
      "ip": null,
      "id": "3d9fc521-1bfa-4d82-b74c-f0761383394c",
      "private_ip": "10.132.159.132",
      "aws_instance_id": "i-d75147d4",
      "backends": 5,
      "layers": [
        "lb"
      ],
      "public_dns_name": null,
      "hostname": "stratus",
      "region": "ap-northeast-1",
      "instance_type": "m1.small",
      "availability_zone": "ap-northeast-1a",
      "private_dns_name": "ip-10-132-159-132.ap-northeast-1.compute.internal",
      "architecture": "i386"
    },
    "agent_version": "104",
    "layers": {
      "lb": {
        "id": "f64dc03e-0c01-4f41-b588-b8289e03deca",
        "name": "Load Balancer",
        "instances": {
          "stratus": {
            "ip": null,
            "elastic_ip": "54.249.245.56",
            "private_ip": "10.132.159.132",
            "aws_instance_id": "i-d75147d4",
            "created_at": "2013-03-13T06:38:58+00:00",
            "status": "online",
            "booted_at": "2013-03-13T06:40:49+00:00",
            "backends": 5,
            "public_dns_name": null,
            "region": "ap-northeast-1",
            "instance_type": "m1.small",
            "availability_zone": "ap-northeast-1a",
            "private_dns_name": "ip-10-132-159-132.ap-northeast-1.compute.internal"
          }
        }
      },
      "php-app": {
        "id": "c38c9a7f-90eb-4764-8ebd-3b48592f57cb",
        "name": "PHP Application Server",
        "instances": {
          "altocumulus": {
            "ip": "54.249.207.244",
            "elastic_ip": null,
            "private_ip": "10.162.54.166",
            "aws_instance_id": "i-2b5d4b28",
            "created_at": "2013-03-13T06:48:12+00:00",
            "status": "online",
            "booted_at": "2013-03-13T06:49:30+00:00",
            "backends": 5,
            "public_dns_name": "ec2-54-249-207-244.ap-northeast-1.compute.amazonaws.com",
            "region": "ap-northeast-1",
            "instance_type": "m1.small",
            "availability_zone": "ap-northeast-1a",
            "private_dns_name": "ip-10-162-54-166.ap-northeast-1.compute.internal"
          },
          "stratocumulus": {
            "ip": "54.249.153.134",
            "elastic_ip": null,
            "private_ip": "10.152.46.168",
            "aws_instance_id": "i-07405604",
            "created_at": "2013-03-13T07:30:05+00:00",
            "status": "online",
            "booted_at": "2013-03-13T07:31:22+00:00",
            "backends": 5,
            "public_dns_name": "ec2-54-249-153-134.ap-northeast-1.compute.amazonaws.com",
            "region": "ap-northeast-1",
            "instance_type": "m1.small",
            "availability_zone": "ap-northeast-1a",
            "private_dns_name": "ip-10-152-46-168.ap-northeast-1.compute.internal"
          }
        }
      }
    },
    "sent_at": 1363160598,
    "rails_stack": {
      "name": null
    }
  },
  "opsworks_custom_cookbooks": {
    "recipes": [

    ],
    "enabled": false
  },
  "deploy": {
    "php_app": {
      "memcached": {
        "host": null,
        "port": 11211
      },
      "rails_env": null,
      "migrate": false,
      "ssl_certificate_ca": null,
      "auto_bundle_on_deploy": true,
      "ssl_support": false,
      "domains": [
        "php_app"
      ],
      "database": {
        "reconnect": true,
        "host": null,
        "database": "php_app",
        "password": null,
        "username": "root"
      },
      "ssl_certificate": null,
      "symlink_before_migrate": {
        "config/opsworks.php": "opsworks.php"
      },
      "application_type": "php",
      "symlinks": {
      },
      "mounted_at": null,
      "restart_command": "echo 'restarting app'",
      "document_root": null,
      "sleep_before_restart": 0,
      "application": "php_app",
      "deploy_to": "/srv/www/php_app",
      "scm": {
        "user": null,
        "repository": "git://github.com/funasaki/helloworld-php.git",
        "password": null,
        "revision": null,
        "scm_type": "git",
        "ssh_key": null
      },
      "ssl_certificate_key": null
    }
  },
  "haproxy": {
    "static_applications": {
    },
    "health_check_method": "GET",
    "rails_applications": {
    },
    "nodejs_backends": [

    ],
    "php_applications": {
      "php_app": {
        "domains": [
          "php_app"
        ],
        "application_type": "php",
        "mounted_at": null
      }
    },
    "enable_stats": true,
    "nodejs_applications": {
    },
    "php_backends": [
      {
        "ip": "10.162.54.166",
        "backends": 10,
        "name": "altocumulus"
      },
      {
        "ip": "10.152.46.168",
        "backends": 10,
        "name": "stratocumulus"
      }
    ],
    "rails_backends": [

    ],
    "stats_url": "/haproxy?stats",
    "static_backends": [

    ],
    "stats_password": "mypassword",
    "stats_user": "opsworks",
    "health_check_url": "/"
  },
  "ssh_users": {
  }
}

さらにログファイルも当然だがあった。

$ ls /var/log/aws/opsworks
installer.log           opsworks-agent.log  user-data.log
opsworks-agent-cli.log  updater.log