AWSの料金表を自動作成したい

AWS の料金一覧画面から Google スプレッドシートに値をコピペするのに疲れたので、なんとか EC2 の料金表を自動生成できないかと思いました。試行錯誤の結果、ようやくデータ構造までは把握できました。

AWS Price List Service API

AWS Price List Service API (AWS Price List Service)で AWS の料金データを取得できます。今回は取っ掛かりとして AWS CLI を使うので、Pricing サブコマンドでやることになります。

この API は、使えるエンドポイントが以下に限られます。

このため、.aws/config は以下のようにしています。

$ cat .aws/config
[default]
output = json
region = us-east-1

Pricing で使えるサブコマンドは、以下の3種類です。

サブコマンド名 機能
describe-services サービスとその属性名の一覧
get-attribute-values サービス毎の属性値の一覧
get-products 価格の一覧

describe-services

describe-services を何も指定せずに呼び出すと、サービスとその属性名の一覧がずらずらと表示されます。なお便宜上、(JSONではなく)テキスト形式で出力しています。

$ aws pricing describe-services --output=text | head -5
SERVICES        AWSBudgets
ATTRIBUTENAMES  productFamily
ATTRIBUTENAMES  servicecode
ATTRIBUTENAMES  groupDescription
ATTRIBUTENAMES  termType

いろんなサービスがありますね。。

$ aws pricing describe-services --output=text | grep ^SERVICES | wc -l
92
$ aws pricing describe-services --output=text | grep ^SERVICES | head -5
SERVICES        AWSBudgets
SERVICES        AWSCloudTrail
SERVICES        AWSCodeCommit
SERVICES        AWSCodeDeploy
SERVICES        AWSCodePipeline

今回目的とするサービス(EC2)の正式なサービス名を調べます。

$ aws pricing describe-services --output=text | grep -i ec2
SERVICES        AmazonEC2

これ以降は、コマンドを発行する際にサービスコードを明示することで、なるべくデータ量を減らすようにします。

AmazonEC2 サービスで使えそうな属性名の候補を調べます。

$ aws pricing describe-services --output=text --service-code AmazonEC2 | wc -l
62
$ aws pricing describe-services --output=text --service-code AmazonEC2 | 
  grep -Ei '(type|cpu|ecu|memory)'
ATTRIBUTENAMES  volumeType
ATTRIBUTENAMES  locationType
ATTRIBUTENAMES  ecu
ATTRIBUTENAMES  gpuMemory
ATTRIBUTENAMES  elasticGpuType
ATTRIBUTENAMES  memory
ATTRIBUTENAMES  vcpu
ATTRIBUTENAMES  termType
ATTRIBUTENAMES  instanceType
ATTRIBUTENAMES  usagetype

AmazonEC2 に限っても、ATTRIBUTENAME(属性名)だけで 62 個もある…。

get-attribute-values

次に “instanceType” という属性名に着目して、その属性値の候補を取得します。

$ aws pricing get-attribute-values --output=text --service-code AmazonEC2 
  --attribute-name instanceType | wc -l
122
$ aws pricing get-attribute-values --output=text --service-code AmazonEC2 
    --attribute-name instanceType | grep -E 't[12]'
ATTRIBUTEVALUES t1.micro
ATTRIBUTEVALUES t2.2xlarge
ATTRIBUTEVALUES t2.large
ATTRIBUTEVALUES t2.medium
ATTRIBUTEVALUES t2.micro
ATTRIBUTEVALUES t2.nano
ATTRIBUTEVALUES t2.small
ATTRIBUTEVALUES t2.xlarge

インスタンスタイプだけで 122 個…。この調子ですべての組み合わせを表示しようとすると、表のサイズが爆発するのは明白です。API サーバにも無意味に負荷をかけそうなので、最初はとりあえず t1.micro の Linux インスタンス(かつ東京リージョンのみ)に絞ってやってみています。

get-products

このサブコマンドで価格の値が取れるのですが、そのままでは使い勝手がよくありません。

$ aws pricing get-products --service-code AmazonEC2  
  --filters Type=TERM_MATCH,Field=instanceType,Value=t1.micro 
            Type=TERM_MATCH,Field=operatingSystem,Value=Linux 
            'Type=TERM_MATCH,Field=location,Value=Asia Pacific (Tokyo)' 
  > t1-micro-linux-tokyo.txt
$ cat t1-micro-linux-tokyo.txt
{
    "PriceList": [
        "{"product":{"productFamily":"Compute Instance","attributes":{"memory(以下、死ぬほど長い文字列)...

jq というコマンドを通すといい感じに整形してくれるらしいのですが、どうもうまくパースしてくれません。いろいろと試してみたところ、配列の中身全体が “” で囲まれているのが問題のようです。ということで、この引用符を外してやると、うまく見えるようになりました。ついでにバックスラッシュも外します。

$ cat t1-micro-linux-tokyo.txt | 
  sed -e 's/\//g' -e 's/"{/{/g' -e 's/}"/}/g' | 
  jq
{
  "PriceList": [
    {
      "product": {
        "productFamily": "Compute Instance",
        "attributes": {
          "memory": "0.613 GiB",
          "vcpu": "1",
          "instanceType": "t1.micro",
          "tenancy": "Shared",
          "usagetype": "APN1-BoxUsage:t1.micro",
          "locationType": "AWS Region",
          "storage": "EBS only",
          "normalizationSizeFactor": "0.5",
          "instanceFamily": "Micro instances",
          "operatingSystem": "Linux",
          "servicecode": "AmazonEC2",
          "physicalProcessor": "Variable",
          "licenseModel": "No License required",
          "ecu": "Variable",
          "currentGeneration": "No",
          "preInstalledSw": "NA",
          "networkPerformance": "Very Low",
          "location": "Asia Pacific (Tokyo)",
          "servicename": "Amazon Elastic Compute Cloud",
          "processorArchitecture": "32-bit or 64-bit",
          "operation": "RunInstances"
        },
        "sku": "ERVWZ4V3UBYH4NQH"
      },
      "serviceCode": "AmazonEC2",
      "terms": {
        "OnDemand": {
          "ERVWZ4V3UBYH4NQH.JRTCKXETXF": {
            "priceDimensions": {
              "ERVWZ4V3UBYH4NQH.JRTCKXETXF.6YS6EN2CT7": {
                "unit": "Hrs",
                "endRange": "Inf",
                "description": "$0.026 per On Demand Linux t1.micro Instance Hour",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.JRTCKXETXF.6YS6EN2CT7",
                "beginRange": "0",
                "pricePerUnit": {
                  "USD": "0.0260000000"
                }
              }
            },
            "sku": "ERVWZ4V3UBYH4NQH",
            "effectiveDate": "2017-12-01T00:00:00Z",
            "offerTermCode": "JRTCKXETXF",
            "termAttributes": {}
          }
        },
        "Reserved": {
          "ERVWZ4V3UBYH4NQH.NQ3QZPMQV9": {
            "priceDimensions": {
              "ERVWZ4V3UBYH4NQH.NQ3QZPMQV9.2TG2D8R56U": {
                "unit": "Quantity",
                "description": "Upfront Fee",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.NQ3QZPMQV9.2TG2D8R56U",
                "pricePerUnit": {
                  "USD": "316"
                }
              },
              "ERVWZ4V3UBYH4NQH.NQ3QZPMQV9.6YS6EN2CT7": {
                "unit": "Hrs",
                "endRange": "Inf",
                "description": "USD 0.0 per Linux/UNIX (Amazon VPC), t1.micro reserved instance applied",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.NQ3QZPMQV9.6YS6EN2CT7",
                "beginRange": "0",
                "pricePerUnit": {
                  "USD": "0.0000000000"
                }
              }
            },
            "sku": "ERVWZ4V3UBYH4NQH",
            "effectiveDate": "2015-04-30T23:59:59Z",
            "offerTermCode": "NQ3QZPMQV9",
            "termAttributes": {
              "LeaseContractLength": "3yr",
              "OfferingClass": "standard",
              "PurchaseOption": "All Upfront"
            }
          },
          "ERVWZ4V3UBYH4NQH.6QCMYABX3D": {
            "priceDimensions": {
              "ERVWZ4V3UBYH4NQH.6QCMYABX3D.2TG2D8R56U": {
                "unit": "Quantity",
                "description": "Upfront Fee",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.6QCMYABX3D.2TG2D8R56U",
                "pricePerUnit": {
                  "USD": "138"
                }
              },
              "ERVWZ4V3UBYH4NQH.6QCMYABX3D.6YS6EN2CT7": {
                "unit": "Hrs",
                "endRange": "Inf",
                "description": "USD 0.0 per Linux/UNIX (Amazon VPC), t1.micro reserved instance applied",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.6QCMYABX3D.6YS6EN2CT7",
                "beginRange": "0",
                "pricePerUnit": {
                  "USD": "0.0000000000"
                }
              }
            },
            "sku": "ERVWZ4V3UBYH4NQH",
            "effectiveDate": "2015-04-30T23:59:59Z",
            "offerTermCode": "6QCMYABX3D",
            "termAttributes": {
              "LeaseContractLength": "1yr",
              "OfferingClass": "standard",
              "PurchaseOption": "All Upfront"
            }
          },
          "ERVWZ4V3UBYH4NQH.38NPMPTW36": {
            "priceDimensions": {
              "ERVWZ4V3UBYH4NQH.38NPMPTW36.2TG2D8R56U": {
                "unit": "Quantity",
                "description": "Upfront Fee",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.38NPMPTW36.2TG2D8R56U",
                "pricePerUnit": {
                  "USD": "100"
                }
              },
              "ERVWZ4V3UBYH4NQH.38NPMPTW36.6YS6EN2CT7": {
                "unit": "Hrs",
                "endRange": "Inf",
                "description": "Linux/UNIX (Amazon VPC), t1.micro reserved instance applied",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.38NPMPTW36.6YS6EN2CT7",
                "beginRange": "0",
                "pricePerUnit": {
                  "USD": "0.0090000000"
                }
              }
            },
            "sku": "ERVWZ4V3UBYH4NQH",
            "effectiveDate": "2016-10-31T23:59:59Z",
            "offerTermCode": "38NPMPTW36",
            "termAttributes": {
              "LeaseContractLength": "3yr",
              "OfferingClass": "standard",
              "PurchaseOption": "Partial Upfront"
            }
          },
          "ERVWZ4V3UBYH4NQH.HU7G6KETJZ": {
            "priceDimensions": {
              "ERVWZ4V3UBYH4NQH.HU7G6KETJZ.2TG2D8R56U": {
                "unit": "Quantity",
                "description": "Upfront Fee",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.HU7G6KETJZ.2TG2D8R56U",
                "pricePerUnit": {
                  "USD": "62"
                }
              },
              "ERVWZ4V3UBYH4NQH.HU7G6KETJZ.6YS6EN2CT7": {
                "unit": "Hrs",
                "endRange": "Inf",
                "description": "Linux/UNIX (Amazon VPC), t1.micro reserved instance applied",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.HU7G6KETJZ.6YS6EN2CT7",
                "beginRange": "0",
                "pricePerUnit": {
                  "USD": "0.0090000000"
                }
              }
            },
            "sku": "ERVWZ4V3UBYH4NQH",
            "effectiveDate": "2015-04-30T23:59:59Z",
            "offerTermCode": "HU7G6KETJZ",
            "termAttributes": {
              "LeaseContractLength": "1yr",
              "OfferingClass": "standard",
              "PurchaseOption": "Partial Upfront"
            }
          },
          "ERVWZ4V3UBYH4NQH.4NA7Y494T4": {
            "priceDimensions": {
              "ERVWZ4V3UBYH4NQH.4NA7Y494T4.6YS6EN2CT7": {
                "unit": "Hrs",
                "endRange": "Inf",
                "description": "Linux/UNIX (Amazon VPC), t1.micro reserved instance applied",
                "appliesTo": [],
                "rateCode": "ERVWZ4V3UBYH4NQH.4NA7Y494T4.6YS6EN2CT7",
                "beginRange": "0",
                "pricePerUnit": {
                  "USD": "0.0180000000"
                }
              }
            },
            "sku": "ERVWZ4V3UBYH4NQH",
            "effectiveDate": "2016-08-31T23:59:59Z",
            "offerTermCode": "4NA7Y494T4",
            "termAttributes": {
              "LeaseContractLength": "1yr",
              "OfferingClass": "standard",
              "PurchaseOption": "No Upfront"
            }
          }
        }
      },
      "version": "20180131042456",
      "publicationDate": "2018-01-31T04:24:56Z"
    }
  ],
  "FormatVersion": "aws_v1"
}

返されるデータの構造がわかったので、後は必要な項目だけを抜き出して CSV で出力してやれば、Google スプレッドシートにインポートで取り込めそうです。ということで、今日はここまでです。


っと、ここまで書いてから投稿しようとしたら、AWS Price List API の使用 とかいうよさげなページがあるのに気づいたのでこれから読みます。。。

(参照)

続きを読む

aws-sdk-phpで5GB以上のファイルをS3にアップロードする方法

何の話?

S3に5GB以上のファイルを、aws-sdk-phpのS3のputObjectを使ってアップロードしようとしたら、以下のエラーが出た。

1ファイルあたりのアップロードできる上限サイズは、5368709120byte(5.36870912GB)なのに、
5506553726byte(5.506553726GB)アップロードしようとしてると怒られている。

Error executing "PutObject" on "https://xxxx.s3.ap-northeast-1.amazonaws.com/path/filename"; 
AWS HTTP error: Client error: `PUT https://xxxx.s3.ap-northeast-1.amazonaws.com/path/filename` resulted in a `400 Bad Request` 
<?xml version='1.0' encoding='utf-8'?>
<error>
    <code>
        EntityTooLarge
    </code>
    <message>
        Your proposed upload exceeds the maxim (truncated...)
    EntityTooLarge (client): Your proposed upload exceeds the maximum allowed size -
        <?xml version='1.0' encoding='utf-8'?>
    </message>
</error>
<error>
    <code>
        EntityTooLarge
    </code>
    <message>
        Your proposed upload exceeds the maximum allowed size
    </message>
    <proposedsize>
        5506553726
    </proposedsize>
    <maxsizeallowed>
        5368709120
    </maxsizeallowed>
    <requestid>
        DCB569101CF240C0
    </requestid>
    <hostid>
        xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    </hostid>
</error>

AWSのよくある質問を見ると

Q: どれほどの量のデータを保存できますか?

格納可能なデータの総量とオブジェクトの数には制限はありません。個別の Amazon S3 オブジェクトのサイズは、最低 0 バイトから最大 5 テラバイトまでさまざまです。1つの PUT にアップロード可能なオブジェクトの最大サイズは 5 GB です。100 MB 以上のオブジェクトの場合は、Multipart Upload 機能を使うことをお考えください。

https://aws.amazon.com/jp/s3/faqs/

総量とオブジェクトの数には制限はないが、1つの PUT にアップロード可能なオブジェクトの最大サイズは 5 GBらしい。
100 MB 以上のオブジェクトの場合は、Multipart Upload 機能を使うことをお考えください、とある。

MultipartUploaderとは

以下のサイトにMultipartUploaderを使って、5GB以上のファイルでもアップロードする方法が書いてある。
最大5TBのファイルまでアップロードできるらしい。
Amazon S3 オブジェクトのサイズの上限までってことか。

With a single PutObject operation, you can upload objects up to 5 GB in size. However, by using the multipart uploads (e.g., CreateMultipartUpload, UploadPart, CompleteMultipartUpload, AbortMultipartUpload), you can upload object up to 5 TB in size.

Amazon S3 Multipart Uploads

MultipartUploaderを使ってみる

composer

aws-sdk-phpがインストールされていることが前提。
composer以外の方法でインストールしてもOK。

composer.json
{
    "autoload": {
        "psr-4": {
        }
    },
    "require": {
        "aws/aws-sdk-php": "3.*"
    }
}

PHPのソースを作成

以下のソースで、5GB以上のファイルもアップロードできた。

<?php

require(dirname(__FILE__) . '/vendor/autoload.php');

use Aws\S3\S3Client;
use Aws\S3\MultipartUploader;
use Aws\Exception\MultipartUploadException;

$s3Client = S3Client::factory([
    'version' => '2006-03-01',
    'key' => 'xxxxxxxx',
    'secret' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    'region' => 'ap-northeast-1'
]);


$bucketname = 'sample-bucket';
$from_path = './bigdata.csv';
$to_path = 'dirname/bigdata.csv';

$uploader = new MultipartUploader($s3Client, $from_path, [
    'bucket' => $bucketname,
    'key'    => $to_path,
]);

try {
    $result = $uploader->upload();
    print_r($result);
    echo $result['ObjectURL'];
} catch (MultipartUploadException $e) {
    echo $e->getMessage();
}

以上

続きを読む

copy files from local to aws S3 Bucket(aws cli + s3 bucket)

                       **AWS CLI and S3 Bucket**

maxresdefault.jpg

In my current project, I need to deploy/copy my front-end code into AWS S3 bucket. But I do not know how to perform it. One of my colleagues found a way to perform this task.

here are the guidelines from start to end, how to install aws cli, how to use aws cli and other functionalities.

So, let’s start from the beginning.
In my mac, I do not installed aws cli, so I got the error when running the following command.
Open your terminal,

$ aws --version

output
-bash: aws: command not found

(Here I got the solution, https://qiita.com/maimai-swap/items/999eb69b7a4420d6ab64)

So now let’s install the brew, if you do not installed yet.
Step1. Install the brew

$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Step2. check the brew version

$ brew -v

output
Homebrew 1.5.2
Homebrew/homebrew-core (git revision 58b9f; last commit 2018-01-24)

Step3. install aws cli, use the following command

$ brew install awscli

Step4. check the aws cli version

$ aws --version

output
aws-cli/1.14.30 Python/3.6.4 Darwin/17.3.0 botocore/1.8.34

that’s great, now it’s time to configure the AWS credential.
Step5. now configure the aws profile

$ aws configure
AWS Access Key ID [None]: <your access key>
AWS Secret Access Key [None]: <your secret key>
Default region name [None]: <your region name>
Default output format [None]: ENTER

All settings are done.
now you can access your s3 bucket.

now from here, we can learn how to manage our bucket.
Managing Buckets
aws s3 commands support commonly used bucket operations, such as creating, removing, and listing buckets.

1.Listing Buckets

$ aws s3 ls

output
2017-12-29 08:26:08 my-bucket1
2017-11-28 18:45:47 my-bucket2

The following command lists the objects in bucket-name/path (in other words, objects in bucket-name filtered by the prefix path/).

$ aws s3 ls s3://bucket-name

2.Creating Buckets

$ aws s3 mb s3://bucket-name

(aws s3 mb command to create a new bucket. Bucket names must be unique.)

3.Removing Buckets
To remove a bucket, use the aws s3 rb command.

$ aws s3 rb s3://bucket-name

By default, the bucket must be empty for the operation to succeed. To remove a non-empty bucket, you need to include the –force option.

$ aws s3 rb s3://bucket-name --force

This will first delete all objects and subfolders in the bucket and then remove the bucket.

Managing Objects
The high-level aws s3 commands make it convenient to manage Amazon S3 objects as well. The object commands include aws s3 cp, aws s3 ls, aws s3 mv, aws s3 rm, and sync. The cp, ls, mv, and rm commands work similarly to their Unix

The cp, mv, and sync commands include a –grants option that can be used to grant permissions on the object to specified users or groups. You set the –grants option to a list of permissions using the following syntax:

--grants Permission=Grantee_Type=Grantee_ID
         [Permission=Grantee_Type=Grantee_ID ...]

Each value contains the following elements:
* Permission – Specifies the granted permissions, and can be set to read, readacl, writeacl, or full.
* Grantee_Type – Specifies how the grantee is to be identified, and can be set to uri, email address, or id.
* Grantee_ID – Specifies the grantee based on Grantee_Type.
* uri – The group’s URI. For more information, see Who Is a Grantee?
* email address – The account’s email address.
* id – The account’s canonical ID.

aws s3 cp file.txt s3://my-bucket/ --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers full=emailaddress=user@example.com

For more details, please go through the aws official link.
https://docs.aws.amazon.com/cli/latest/userguide/using-s3-commands.html

thank you for taking your precious time to read.

Enjoy coding.:grinning::grinning:

Thanks & Best Regards,
Alok Rawat

続きを読む

Linux のログイン・ログオフ履歴を Cloudwatch Logs に送信する

サマリ

Linux のログイン/ログオフの履歴(だけ)を Cloudwatch Logs に送りたかった。
rsyslog から sshd のログだけ抽出して Cloudwatch Logs Agent で送った。できた。

要件

Linux へのログイン・ログオフの履歴を Cloudwatch Logs に保存する必要があり、Cloudwatch Logs Agent をインストールして /var/log/secure を Cloudwatch Logs に送信する。
ただし、トラフィック量の都合で secure 全て送るのはよろしくないのでいい感じに絞ったものを送信したい。

SSH ログイン時に出力されるログには2種類あり、

  1. sshd プロセスが出力する rsyslog

    • /var/log/secure
  2. login プロセス出力するログ達(バイナリ形式)
    • /var/log/wtmp (ログイン成功ログ)

      • last コマンドで表示、新しいものが上で並ぶ
    • /var/log/btmp (ログイン失敗ログ)
      • lastb コマンドで表示、新しいものが上で並ぶ

送信するにはテキストである必要があるため、

  1. rsyslog からうまいこと sshd プロセスのログだけを別ファイルにする

    • rsyslog で出力されたログをCloudwatch Logs Agent で送信する
  2. last/lastbコマンドを実行し、結果をログファイルに出力するシェルスクリプトを作成する。その際、時系列降順に直す必要がある。
    • cronで定期的に実行し、ログをCloudwatch Logs Agent で送信する

の2パターン考えられるが、楽そうな前者を試す。

設定手順

環境

  • Red Hat Enterprise Linux 7.4 (HVM)
  • awscli-cwlogs 1.4.4

SSHログの抽出

適当な EC2 インスタンスを起動。

要件としては、rsyslog の secure ログ /var/log/secure| grep 'sshd'したような結果が出力できればよさそう。そのほかの secure ログはいらない。

console
$ sudo cat /var/log/secure | grep 'sshd'
略
Jan 23 19:41:46 HOSTNAME sshd[5106]: Server listening on 0.0.0.0 port 22.
Jan 23 19:41:46 HOSTNAME sshd[5106]: Server listening on :: port 22.
Jan 23 20:40:54 HOSTNAME sshd[1976]: pam_unix(sshd:session): session closed for user ec2-user
Jan 23 20:47:46 HOSTNAME sshd[4914]: Accepted publickey for ec2-user from 10.0.0.2 port 61646 ssh2: RSA SHA256:xxx
Jan 23 20:47:46 HOSTNAME sshd[4914]: pam_unix(sshd:session): session opened for user ec2-user by (uid=0)
Jan 23 20:49:12 HOSTNAME sshd[4914]: pam_unix(sshd:session): session closed for user ec2-user

rsysgにはプロパティベース フィルタというものがあり、 :property, [!]compare-operation, "value"
programname でフィルタがかけられる。これを利用すれば特定のプロセスのログだけ別ファイルに出力することが可能。
なので rsyslog の設定をしていく。secure_sshd という新しいログファイルに sshd プロセスのログだけを出力する設定を追記。

/etc/rsyslog.conf
# sshd ログを別ファイルにも出力
:programname, isequal, "sshd" /var/log/secure_sshd
console
sudo service rsyslog restart

ログイン・ログオフしてから良い感じにログが出ていること確認できた。

console
$ sudo cat /var/log/secure_sshd
Jan 24 03:08:55 HOSTNAME sshd[9308]: Accepted publickey for ec2-user from 10.0.0.3 port 60196 ssh2: RSA SHA256:xxx
Jan 24 03:08:55 HOSTNAME sshd[9308]: pam_unix(sshd:session): session opened for user ec2-user by (uid=0)
Jan 24 03:09:14 HOSTNAME sshd[9308]: pam_unix(sshd:session): session closed for user ec2-user

Cloudwatch Agent 側設定

EC2インスタンスに CloudwatchLogs 用のポリシーをアタッチ。

Send2Cloudwatch
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:DescribeLogStreams"
    ],
      "Resource": [
        "arn:aws:logs:*:*:*"
    ]
  }
 ]
}

パッケージ更新、awslogsインストール

console
sudo yum update -y
# ubuntu,centos,redhat はこう
curl https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py -O
sudo python ./awslogs-agent-setup.py --region us-east-1
# Amazon Linux ならこっち
# sudo yum install awslogs

バージョン確認

console
$ /var/awslogs/bin/awslogs-version.sh
略
/etc/cron.d/awslogs_log_rotate version:
# Version: 1.4.3
CloudWatch Logs Plugin Version:
You are using pip version 6.1.1, however version 9.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
---
Metadata-Version: 1.1
Name: awscli-cwlogs
Version: 1.4.4
Summary: AWSCLI CloudWatch Logs plugin
Home-page: http://aws.amazon.com/cli/
Author: Amazon
Author-email: UNKNOWN
License: Amazon Software License
Location: /var/awslogs/lib/python2.7/site-packages
Requires: awscli, six, python-dateutil
AWS CLI Version

ログファイル送信設定、先ほどの secure_sshd を指定する

/var/awslogs/etc/awslogs.conf
# 元のmessageログ送信は今回使わないのでコメントアウト
# [/var/log/messages]
# datetime_format = %b %d %H:%M:%S
# file = /var/log/messages
# buffer_duration = 5000
# log_stream_name = {instance_id}
# initial_position = start_of_file
# log_group_name = /var/log/messages

# 普通にsecureログ送るならこう
# [/var/log/secure]
# datetime_format = %b %d %H:%M:%S
# file = /var/log/secure
# buffer_duration = 5000
# log_stream_name = {instance_id}
# initial_position = start_of_file
# log_group_name = /var/log/secure

[/var/log/secure_sshd]
datetime_format = %b %d %H:%M:%S
file = /var/log/secure_sshd
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = /var/log/secure_sshd

必要に応じてプロキシ設定

/var/awslogs/etc/proxy.conf
HTTP_PROXY=proxyserver:8080
HTTPS_PROXY=proxyserver:8080
NO_PROXY=

サービス再起動&起動設定

console
sudo service awslogs start
sudo chkconfig awslogs on

Logs への送信ログ確認するなら

console
sudo tail /var/log/awslogs.log

動きました

image.png

参考

CloudWatch Logs エージェントのリファレンス – Amazon CloudWatch ログ
クイックスタート: 実行中の EC2 Linux インスタンスに CloudWatch Logs エージェントをインストールして設定する – Amazon CloudWatch ログ
Linux環境設定/sshによる不正アクセスを確認する – Linuxと過ごす
Rsyslog – Wikinote
システム管理の基礎 syslogdの設定をマスターしよう:Linux管理者への道(3) – @IT
必読!ログファイルとディレクトリ | Think IT(シンクイット)

続きを読む

AWS AppSyncとReactでToDoアプリを作ってみよう (2)DataSourceとResolverの設定

はじめに

前回の記事で定義したGraphQLスキーマはAPIのインターフェースの定義でした。
このインターフェースを使ってAPIにアクセスがあった際に、データを保存する先のリソース(DataSource)の作成と連携の部分を設定していきます。
AWS AppSyncでは、Resolverを作成することで、DataSourceとGraphQLスキーマとの紐付けを行います。

リソース(DataSource)の作成

今回の例では、GraphQLスキーマに定義したTodo型からDynamoDBのテーブルを作成します。
まずは、コンソール画面から、「AWS AppSync > 作成したプロジェクト > Schema」を開き、画面右上の「Create Recources」をクリックします。

CreateRecouces.png

次の画面では、定義済みのGraphQLスキーマから使用する型を選択します。
今回はTodoを選択しました。

スクリーンショット 2018-01-22 6.07.41.png

使用する型を選択すると、自動でテーブル名、テーブルの構成が入力されます。
今回は、idをプライマリキーとしました。

スクリーンショット 2018-01-22 7.05.49.png

ここまでの項目を入力すると、画面最下部にテーブル定義を元に、自動で追加されるスキーマ定義のプレビューが表示されます。
最後に、「Create」ボタンをクリックすると、DynamoDBテーブルが作成されます。

スクリーンショット 2018-01-22 7.05.59.png

Resolverの追加と修正

前の手順では、GraphQLスキーマから自動でDynamoDBとResolverのプロビジョニングを行いましたが、一部、定義元のスキーマと紐付いていない点があるので、追加・修正していきます。

getTodos

getTodosには、Resolverが紐付けられていないので、新規で追加します。

「Schema > Query > getTodos: [Todo]」の「Attach」をクリックします。
次の画面では、作成済みのDataSourceから紐付けるテーブルを選択します。
今回はTodoTabeを選択しました。

スクリーンショット 2018-01-22 6.42.08.png

次に、リクエストのマッピングを行います。
「Paginated scan」のテンプレートをベースに、次のように変更しました。

RequestMappingTemplate
{
    "version" : "2017-02-28",
    "operation" : "Scan"
}

レスポンスのマッピングは次のようになります。

ResponseMappingTemplate
$utils.toJson($context.result.items)

最後に、画面右下の「Save」をクリックしてResolverの設定を保存します。

getTodo

これは、自動で追加されたQueryです。
今回のToDoアプリでは、item一件ごとに取得するGetItem操作は不要なので、削除します。

allTodo

これは、自動で追加されたQueryです。
こちらは、getTodosと処理が重複するため削除します。
(ページネーション処理も自動で設定済みのようなので、こちらを使うのがよさそうですが…)

addTodo

自動で追加されたMutation、putTodoの内容をこちらに移行すれば良さそうです。

RequestMappingTemplate
{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key": {
        "id": { "S" : "${context.arguments.id}"}
    },
    "attributeValues" : {
        "id": {  "S": "${context.arguments.id}" },
        "title": {  "S": "${context.arguments.title}" },
        "description": {  "S": "${context.arguments.description}" },
        "completed": {  "B": "${context.arguments.completed}" }
    }
}
ResponseMappingTemplate
$utils.toJson($context.result)

updateTodo

updateTodoには、Resolverが紐付けられていないので、新規で追加します。
getTodosで行った新規追加手順と同様に操作を行い、次のテンプレートを設定します。

RequestMappingTemplate
{
    "version" : "2017-02-28",
    "operation" : "UpdateItem",
    "key": {
        "id": { "S" : "${context.arguments.id}"}
    },
    "update" : {
        "expression" : "SET title = :title, description = :description, completed = :completed",
        "expressionValues" : {
            ":title" : { "S": "${context.arguments.title}" },
            ":description" : { "S": "${context.arguments.description}" },
            ":completed" : { "BOOL": ${context.arguments.completed} }
       }
    }
}
ResponseMappingTemplate
$utils.toJson($context.result)

更新操作は、DynamoDBの更新式の指定が必須となっているようでうです。

deleteTodo

こちらは、自動でしっかりとマッピングされているので、そのまま使用します。

putTodo

これは、自動で追加されたMutationです。
こちらは、addTodoと処理が重複するため削除します。

以上で、Resolverの設定が終わりました。

APIの動作確認

作成したAPIの動作確認を行ってみます。
コンソール画面から、「AWS AppSync > 作成したプロジェクト > Queries」を開き、画面左側のエディターエリアにクエリを入力し「▶」をクリックしてクエリを実行します。

スクリーンショット 2018-01-22 22.37.05.png

MutationとQueryそれぞれの項目を動作確認してみたいと思います。

addTodo

まずは、データを追加してみます。

Query
mutation addTodo {
  addTodo(
    id: "0651ed86-9314-4267-9bcf-7143b785f173"
    title: "髪を切る"
    description: "来週までには"
    completed: false
  ) {
    id
    title
    description
    completed
  }
}

次のようなレスポンスが返ってくれば成功です。

Response
{
  "data": {
    "addTodo": {
      "id": "0651ed86-9314-4267-9bcf-7143b785f173",
      "title": "髪を切る",
      "description": "来週までには",
      "completed": false
    }
  }
}

getTodos

事前に何件かデータを追加した状態で以下のクエリを実行します。

Query
query {
  getTodos {
    id
    title
    description
    completed
  }
}
Response
{
  "data": {
    "getTodos": [
      {
        "id": "f163372a-8b54-4da4-9237-911a64067517",
        "title": "豆腐を食べる",
        "description": "腐りそう",
        "completed": false
      },
      {
        "id": "0cbab86a-ad72-41b4-a63d-9ce3f9a7d552",
        "title": "Qiita書く",
        "description": "あと2本",
        "completed": false
      },
      {
        "id": "0651ed86-9314-4267-9bcf-7143b785f173",
        "title": "髪を切る",
        "description": "来週までには",
        "completed": false
      }
    ]
  }
}

updateTodo

Query
mutation updateTodo {
  updateTodo(
    id: "0651ed86-9314-4267-9bcf-7143b785f173"
    title: "部屋を掃除する"
    description: "さらっと済ます"
    completed: false
  ) {
    id
    title
    description
    completed
  }
}

※ Responseは省略

deleteTodo

Query
mutation deleteTodo {
  deleteTodo(
    id: "0651ed86-9314-4267-9bcf-7143b785f173"
  ) {
    id
    title
    description
    completed
  }
}

対象のitemのidを指定して、削除を行います。

※ Responseは省略

最後に

今回は、定義したGraphQLスキーマから自動でリソースを作成しましたが、AppSyncのコンソールからは、全て手動でリソースを用意することもできます。必要に応じて使い分けると良さそうです。
次回は、作成したGraphQL APIと連携するReactフロントエンドの実装を行っていく予定です。

参考

Attaching a Data Source -AWS AppSync
Provision from Schema -AWS AppSync
Resolver Mapping Template Reference for DynamoDB -AWS AppSync

続きを読む

IDCFオブジェクトストレージ AWS CLI エラー 【The authorization mechanism you have provided (AWS4-HMAC-SHA256) is not supported.】

現象

IDCFオブジェクトストレージ向けの AWS CLI S3 コマンドがエラーを吐く

$ aws --endpoint-url https://ds.jp-east.idcfcloud.com s3 ls
An error occurred (InvalidRequest) when calling the ListBuckets operation: The authorization mechanism you have provided (AWS4-HMAC-SHA256) is not supported.

原因

リクエスト認証には、v2とv4があり最新のawsの認証はデフォルトでv4になっている。
しかし、IDCFオブジェクトストレージの認証はv2になっており、v4認証でアクセスするとエラーとなる。

対策

リクエスト認証での署名バージョンの指定が可能なので、v4からv2に変更する。

$ aws configure set default.s3.signature_version s3

ちなみにv4を指定する場合はこう

$ aws configure set default.s3.signature_version s3v4

参考リンク

http://docs.openio.io/master/source/user-guide/awscli.html

続きを読む

Amazon SageMakerでml.p2.xlargeを使おうとしたらResourceLimitExceededって怒られた

事象

Amazon SageMakerで ml.p2.xlarge を使って学習させようとしたら以下のエラーが出て学習ができなかった。

ResourceLimitExceeded: An error occurred (ResourceLimitExceeded) when calling the CreateTrainingJob operation: 
The account-level service limit for training-job/ml.p2.xlarge is 0 Instances, with current utilization of 0 Instances and a request delta of 1 Instances. 
Please contact AWS support to request an increase for this limit.

原因

AWSでは利用できるリソースに制限があります。
詳しくはこちらのページをご確認ください。

Amazon SageMakerにも制限があり、こちらでは ml.p2.xlarge インスタンス のデフォルトの制限は 1 となっています。

対策

AWSのサポートに連絡して制限を緩和してもらいましょう。

  1. AWSのコンソールにログイン
  2. 右上の サポート から サポートセンター のページを表示
  3. ケースの作成 を押下
  4. 内容で サービス制限の増加 を選択
  5. 制限タイプで SageMaker を選択
  6. リージョン、リソースタイプ、制限をそれぞれ選択
  7. 新しい制限値を入力
  8. 適当に理由を書いて 送信 を押下

1営業日程度で対応してくれます。
海外のリージョンの申請は海外の担当部署と調整が必要らしく、少し時間がかかるかも

他のサービスも色々制限があったりするので、申請方法を覚えておきましょう。

続きを読む