Amazon Linuxで残りディスク容量アラートを設定

メトリクス送信設定

CloudWatchのメトリクスをLinuxから送信して、ディスク容量が減ったらアラートメールを送信するようにする。

Amazon Linux

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/mon-scripts.html

http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/mon-scripts.html

https://aws.amazon.com/code/8720044071969977

設定対象のLinuxで作業

Metrics通知ツール本体の前に、使っているライブラリ?をインストール。

sudo yum install perl-Switch perl-DateTime perl-Sys-Syslog perl-LWP-Protocol-https

本体をダウンロード。

mkdir ~/cloudwatch/
cd ~/cloudwatch/
curl http://aws-cloudwatch.s3.amazonaws.com/downloads/CloudWatchMonitoringScripts-1.2.1.zip -O

解凍して、aws-scripts-mon/ を /usr/local/cloudwatch/ の下に移動。

sudo mkdir /usr/local/cloudwatch
sudo mv aws-scripts-mon/ /usr/local/cloudwatch/

IAMユーザーを作成して、アクセスキーを設定。

cd /usr/local/cloudwatch/aws-scripts-mon
cp awscreds.template awscreds.conf
vi awscreds.conf

IAM

IAMユーザーにアタッチしたポリシー。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:PutMetricData",
                "cloudwatch:GetMetricStatistics",
                "cloudwatch:ListMetrics",
                "ec2:DescribeTags"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

↓だとダメだった。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "cloudwatch:PutMetricData",
        "cloudwatch:GetMetricStatistics",
        "cloudwatch:ListMetrics",
        "ec2:DescribeTags"
    ],
      "Resource": [
        "arn:aws:logs:*:*:*",
        "arn:aws:cloudwatch:*:*:*"        
    ]
  }
 ]
}

cronに設定

cronに設定前にコマンドラインから試す。

/usr/local/cloudwatch/aws-scripts-mon/mon-put-instance-data.pl --disk-path=/ --disk-space-util --disk-space-used --disk-space-avail

crontab -e

*/5 * * * * /usr/local/cloudwatch/aws-scripts-mon/mon-put-instance-data.pl --disk-path=/ --disk-space-util --disk-space-used --disk-space-avail --from-cron

以上でMetrics送信の設定は完了。
動いているかの確認は、AWS Management Console の CloudWatchで

Metrics > Linux System > Filesystem, InstanceId, MountPath

残りディスク容量が減った時のアラートメールは、AWS Consoleでやる。

Alarms mail

AWS Management Console の CloudWatchに行く(インスタンスが動いているリージョン)

Alarms > Create Alarm
Search Metrics

DiskSpaceUtilization

で検索。
チェックボックスをチェックして、Name, Description, >= 80
で作成。
メール送信の機能は AWS SNS の機能を使っているらしい。

メトリクスではなくてCloudWatchにログを出力(メモ)

CloudWatchにログを出力することもできるらしい。
この手順はMetrics送信の設定の前にやったけど、これじゃなかった。

この記事の通りにやった。
http://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/QuickStartEC2Instance.html

2017-02-06 02:06:45,273 - cwlogs.threads - ERROR - 12442 - Thread-23 - Exception caught in <EventBatchPublisher(Thread-23, started daemon 139840766506752)>
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/cwlogs/threads.py", line 58, in run
    self._run()
  File "/usr/lib/python2.7/dist-packages/cwlogs/push.py", line 1391, in _run
    self._publish_event_batch()
  File "/usr/lib/python2.7/dist-packages/cwlogs/push.py", line 1198, in _publish_event_batch
    self.sequence_token = self._put_log_events(self.event_batch)
  File "/usr/lib/python2.7/dist-packages/cwlogs/push.py", line 1236, in _put_log_events
    response = self.logs_service.put_log_events(**params)
  File "/usr/lib/python2.7/dist-packages/botocore/client.py", line 159, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/usr/lib/python2.7/dist-packages/botocore/client.py", line 483, in _make_api_call
    operation_model, request_dict)
  File "/usr/lib/python2.7/dist-packages/botocore/endpoint.py", line 117, in make_request
    return self._send_request(request_dict, operation_model)
  File "/usr/lib/python2.7/dist-packages/botocore/endpoint.py", line 142, in _send_request
    request = self.create_request(request_dict, operation_model)
  File "/usr/lib/python2.7/dist-packages/botocore/endpoint.py", line 126, in create_request
    operation_name=operation_model.name)
  File "/usr/lib/python2.7/dist-packages/botocore/hooks.py", line 227, in emit
    return self._emit(event_name, kwargs)
  File "/usr/lib/python2.7/dist-packages/botocore/hooks.py", line 210, in _emit
    response = handler(**kwargs)
  File "/usr/lib/python2.7/dist-packages/botocore/signers.py", line 90, in handler
    return self.sign(operation_name, request)
  File "/usr/lib/python2.7/dist-packages/botocore/signers.py", line 147, in sign
    auth.add_auth(request)
  File "/usr/lib/python2.7/dist-packages/botocore/auth.py", line 314, in add_auth
    raise NoCredentialsError
NoCredentialsError: Unable to locate credentials

sudo vi /var/log/awslogs.log
を書き換えてリスタート
sudo service awslogs restart

2017-02-06 02:10:23,622 - cwlogs.push.reader - INFO - 12842 - Thread-4 - Start reading file from 0.
2017-02-06 02:10:25,109 - cwlogs.push.publisher - WARNING - 12842 - Thread-2 - Caught exception: An error occurred (AccessDeniedException) when calling the PutLogEvents operation: User: arn:aws:iam::9915xxxxxxxxxx:user/mmr2host-awslogs is not authorized to perform: logs:PutLogEvents on resource: arn:aws:logs:us-east-1:9915xxxxxxxxxx:log-group:/var/log/messages:log-stream:i-5ca0f181
2017-02-06 02:10:25,110 - cwlogs.threads - ERROR - 12842 - Thread-2 - Exception caught in <EventBatchPublisher(Thread-2, started daemon 139899077621504)>
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/cwlogs/threads.py", line 58, in run
    self._run()
  File "/usr/lib/python2.7/dist-packages/cwlogs/push.py", line 1391, in _run
    self._publish_event_batch()
  File "/usr/lib/python2.7/dist-packages/cwlogs/push.py", line 1198, in _publish_event_batch
    self.sequence_token = self._put_log_events(self.event_batch)
  File "/usr/lib/python2.7/dist-packages/cwlogs/push.py", line 1236, in _put_log_events
    response = self.logs_service.put_log_events(**params)
  File "/usr/lib/python2.7/dist-packages/botocore/client.py", line 159, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/usr/lib/python2.7/dist-packages/botocore/client.py", line 494, in _make_api_call
    raise ClientError(parsed_response, operation_name)
ClientError: An error occurred (AccessDeniedException) when calling the PutLogEvents operation: User: arn:aws:iam::9915xxxxxxxxxx:user/mmr2host-awslogs is not authorized to perform: logs:PutLogEvents on resource: arn:aws:logs:us-east-1:9915xxxxxxxxxx:log-group:/var/log/messages:log-stream:i-5ca0f181
2017-02-06 02:21:13,763 - cwlogs.push.reader - INFO - 12842 - Thread-24 - Replay events end at 14798.
2017-02-06 02:21:13,763 - cwlogs.push.reader - INFO - 12842 - Thread-24 - Start reading file from 0. 
2017-02-06 02:21:14,890 - cwlogs.push.publisher - WARNING - 12842 - Thread-23 - Caught exception: An error occurred (ResourceNotFoundException) when calling the PutLogEvents operation: The specified log group does not exist. 
2017-02-06 02:21:14,890 - cwlogs.push.batch - INFO - 12842 - Thread-23 - Creating log group /var/log/messages.
2017-02-06 02:21:15,081 - cwlogs.push.batch - INFO - 12842 - Thread-23 - Creating log stream i-5ca0f181.
2017-02-06 02:21:15,316 - cwlogs.push.publisher - INFO - 12842 - Thread-23 - Log group: /var/log/messages, log stream: i-5ca0f181, queue size: 0, Publish batch: {'skipped_events_count': 0, 'first_event': {'timestamp': 1486264861000, 'start_position': 0L, 'end_position': 151L}, 'fallback_events_count': 0, 'last_event': {'timestamp': 1486345988000, 'start_position': 14706L, 'end_position': 14798L}, 'source_id': '9eb733a4a488d353c22b89549724bc1e', 'num_of_events': 159, 'batch_size_in_bytes': 18773}
2017-02-06 02:21:19,437 - cwlogs.push.publisher - INFO - 12842 - Thread-23 - Log group: /var/log/messages, log stream: i-5ca0f181, queue size: 0, Publish batch: {'skipped_events_count': 0, 'first_event': {'timestamp': 1486347485000, 'start_position': 14798L, 'end_position': 14900L}, 'fallback_events_count': 0, 'last_event': {'timestamp': 1486347485000, 'start_position': 14984L, 'end_position': 15076L}, 'source_id': '9eb733a4a488d353c22b89549724bc1e', 'num_of_events': 3, 'batch_size_in_bytes': 353}

ログの出力場所

正しく設定できているはずなのに、CloudWatchに出てこないと思ったら、
us-east-1 (US East (N. Virginia)) に出来ていた。
監視対象は us-west-2 (US West (Oregon))にあるのに。
yumで入れた設定ファイルの初期値で region = us-east-1 と書いてある。

[plugins]
cwlogs = cwlogs
[default]
region = us-east-1

PostgreSQLのリプリケーションをしてみるテスト

準備

postgresql94
AWS上にt1.smallでPostgresqlが動いているAmazon Linuxを2台構築。

Amazon Linux

$ cat /etc/os-release 
NAME="Amazon Linux AMI"
VERSION="2016.09"
ID="amzn"
ID_LIKE="rhel fedora"
VERSION_ID="2016.09"
PRETTY_NAME="Amazon Linux AMI 2016.09"
ANSI_COLOR="0;33"
CPE_NAME="cpe:/o:amazon:linux:2016.09:ga"
HOME_URL="http://aws.amazon.com/amazon-linux-ami/"

参考にしたウェブサイト

PostgreSQL レプリケーション構成を組んでみる - tom__bo’s Blog

PostgreSQL9.4でストリーミングレプリケーションする - マコーの日記

エラー1

-bash-4.2$ pg_basebackup -h 172.40.24.192 -p 5432 -D /var/lib/pgsql94/data --xlog --progress --verbose
pg_basebackup: could not connect to server: could not connect to server: Connection timed out
    Is the server running on host "172.40.24.192" and accepting
    TCP/IP connections on port 5432?

AWS の security group に自分自身のsgを許可(5432)

エラー2

-bash-4.2$ pg_basebackup -h 172.40.24.192 -p 5432 -D /var/lib/pgsql94/data --xlog --progress --verbose
pg_basebackup: could not connect to server: FATAL:  no pg_hba.conf entry for replication connection from host "172.40.135.122", user "postgres", SSL off

Postgresql doesn't accept replication connection - Database Administrators Stack Exchange

-bash-4.2$ diff pg_hba.conf pg_hba.conf.2017203 
85,86d84
< host    all             all             172.40.135.122/32        trust
< host    replication     postgres        172.40.135.122/32        trust

pg_basebackup が動いた。

-bash-4.2$ pg_basebackup -h 172.40.24.192 -p 5432 -D /var/lib/pgsql94/data --xlog --progress --verbose
transaction log start point: 0/E000028 on timeline 1
51646/51646 kB (100%), 1/1 tablespace                                         
transaction log end point: 0/E000128
pg_basebackup: base backup completed

メモ

Amazon Linux の場合、
recovery.conf.sample

/usr/share/pgsql94/recovery.conf.sample
にあった。

エラー3

INSERT文が止まる。
アプリも動かない(nginx 504 error: Gateway Timeout)

app1=> select application_name, client_addr, backend_start, state, sync_state from pg_stat_replication;
 application_name | client_addr | backend_start | state | sync_state 
------------------+-------------+---------------+-------+------------
 slave01          |             |               |       | 
(1 row)

参考にしたウェブサイトと違って client_addr や state などが空になっていた。
ただ、この状態はエラーの原因ではなかった。

http://dba.stackexchange.com/questions/50281/postgresql-replication-pg-stat-replication-is-showing-empty-columns

psql から INSERTして応答がなかったので、controll + c した時のメッセージ。

Cancel request sent
WARNING:  canceling wait for synchronous replication due to user request
DETAIL:  The transaction has already committed locally, but might not have been replicated to the standby.
INSERT 0 1

このエラーは、
master db の postgresql.conf に書く、synchronous_standby_names の値と
slave db の recovery.conf に書く、primary_conninfo の中の値が違っていると発生するっぽい。
レコード自体は作られていた。

postgresql.conf in master db.
synchronous_standby_names = 'slave01' # standby servers that provide sync rep

recovery.conf in slave db.
primary_conninfo = 'host=172.40.24.192 port=5432 application_name=slave01'

cronで作成日時から一定期間過ぎたファイルを削除

メモ:
cronで作成日時から一定期間過ぎたファイルを削除

MAILTO=""
# delete files older than 3 days
# 1 3,15 * * * find /var/www/app1/shared/docs/ -maxdepth 2 -type f -ctime +3 -delete

1 3,15 * * * find /var/www/app1/shared/docs/input/ -maxdepth 1 -type f -ctime +3 -delete
5 3,15 * * * find /var/www/app1/shared/docs/output/ -maxdepth 1 -type f -cmin +720 -delete

ansistranoのafter_symlinkでsudo(become)を実行する

ansible の YAML

ansible ansistrano の after_symlink hook で
/etc/init.d/
シンボリックリンクを作る。

- name: initd symlink
  become: true
  file:
    state: link
    src: /var/www/app1/current/deploy/initd/app1_uwsgi
    #dest: /home/user1/app1_uwsgi
    dest: /etc/init.d/app1_uwsgi
    mode: "u=rwx,g=rx,o=rx"

sudoをするにはbecomeを使うと書いてあったけど、
指定の方法が分からなかった。
“配列の中にハッシュをネスト” という方法で書かないといけないっぽい。

http://docs.ansible.com/ansible/become.html

http://www.task-notes.com/entry/20150922/1442890800

ansible-playbook -i inventory/hosts/localvm playbook/deploy.yml -K

ansible-playbook コマンドの最後に -K を付けると最初にsudo passwordを聞かれる。
Ansible, sudoパスワード要求を忘れただけでめんどくなる - Goldstine研究所

エラーメッセージ

その1

fatal: [192.168.3.43]: FAILED! => {"failed": true, "reason": "no action detected in task. This often indicates a misspelled module name, or incorrect module path.\n\nThe error appears to have been in '/Users/aaa/PycharmProjects/app1/deploy/playbook/ansistrano/after_symlink.yml': line 2, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- tasks:\n  ^ here\n\n\nThe error appears to have been in '/Users/aaa/PycharmProjects/app1/deploy/playbook/ansistrano/after_symlink.yml': line 2, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- tasks:\n  ^ here\n"}

その2

fatal: [192.168.3.43]: FAILED! => {"failed": true, "reason": "Syntax Error while loading YAML.\n\n\nThe error appears to have been in '/Users/aaa/PycharmProjects/app1/deploy/playbook/ansistrano/after_symlink.yml': line 4, column 18, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n- name: create django static files\n    django_manage:\n                 ^ here\n"}

完成品

PycharmProjects/app1/deploy/playbook/ansistrano/after_symlink.yml

- name: create django static files
  django_manage:
    command: collectstatic
    app_path: "{{ ansistrano_deploy_to }}/current/"
    virtualenv: "/home/user1/.pyenv/versions/app1/"


- name: init.d app1_uwsgi symlink
  become: true
  file:
    state: link
    src: /var/www/app1/current/deploy/initd/app1_uwsgi
    #dest: /home/user1/app1_uwsgi
    dest: /etc/init.d/app1_uwsgi
    mode: "u=rwx,g=rx,o=rx"

- name: init.d app1_celeryd symlink
  become: true
  file:
    state: link
    src: /var/www/app1/current/deploy/initd/app1_celeryd
    dest: /etc/init.d/app1_celeryd
    mode: "u=rwx,g=rx,o=rx"

- name: restart app1_uwsgi
  become: true
  service:
    name: app1_uwsgi
    state: restarted

- name: restart app1_celeryd
  become: true
  service:
    name: app1_celeryd
    state: restarted

lsのソースコードを読む 2017

lsのソースコードを読んでみたくなったのでメモ。
lsコマンドをハックしてみよう - Yahoo! JAPAN Tech Blog

lsのソースを読みました - mfumiの日記

https://svnweb.freebsd.org/base/head/bin/ls/

当初の目標
- Visual Studio Codeでステップ実行
- ソースを書き換えてファイル名がabc.txtのファイルは表示しないようにする

色々試してMacOS Sierra 10.12.2 とxcodeでビルドとステップ実行ができたので、
Visual Studio Codeじゃなくてxcodeにした。

https://opensource.apple.com/

ファイルの取得

MacOSのlsコマンドのソースコードを取得する。
自分のMac(Sierra 10.12.2)
file_cmds-242.tar.gz
をダウンロード。
https://opensource.apple.com/tarballs/file_cmds/file_cmds-264.30.2.tar.gz

後で、
libutil-47.30.1 と Libinfo-503.30.1
も必要になった。

xcode

AppStoreから無料ダウンロード。

cocoa - Unable to build using Xcode 4 - The selected run destination is not valid for this action - Stack Overflow

ls ビルド設定 (Build Settings)

Project navigator トップ(root)の file_cmds をクリック。
2段目のfile_cmdsをクリックしてlsを選択。
f:id:kubotti:20170120153242p:plain

Debug構成

Project navigator トップ(root)の file_cmds をクリック。 2段目でfile_cmdsを選択。
Info > Configurations
で + をクリックして、Duplicate
Debugという構成を作成。
optimization
 

エラー

何回かやっていたら以下のエラーが出た。

The run destination My Mac is not valid for Running

Build Settings
Base SDKmacOS 10.12
に変更。

ClipStudioPluginSDKのビルドが出来ない[mac] - Qiita

membershipPriv.h not found

ビルドしたらエラーが出た。

/Users/kubotad/codes/ls/file_cmds-264.30.2/ls/print.c:56:10: 'membershipPriv.h' file not found

EI Capitanでsudo付けているOperation not permittedが出た時の対処法 - いつかエンジニアになりたい

https://opensource.apple.com/release/macos-10122.html
libutil-47.30.1 と Libinfo-503.30.1
をダウンロード。
解凍
http://www.ict-fractal.com/blog/2012/07/xcode.html

Search Pathsに追記

2.Build Settingsの一覧が表示されますので、Search PathsカテゴリのHeader Search Pathsという項目を見つけて下さい。

3. Header Search Pathsをダブルクリックすると項目の編集画面が開きます。
 編集画面で+ボタンをクリックすると項目が追加されますので、そこにパスを入力して下さい。
 ※パスはダブルクォーテーションで括りましょう。

Header Search Path
"../Libinfo-503.30.1/membership.subproj"
"../libutil-47.30.1"

How do I use a relative path in Xcode project settings? - Stack Overflow

実行ファイル出力先

Project navigator
に Products というディレクトリ的なものが表示されているけど実物はない。
詳細の Full Pathに以下のPathと書いてあった。

~/Library/Developer/Xcode/DerivedData/file_cmds-bocccevvdifphpdyuxszwxcbgtxo/Build/Products/Release

実行時引数

http://stackoverflow.com/questions/1698830/giving-command-line-arguments-in-xcode-in-c-program

Keyboard shortcut is 
command  shift <

メニューの
Product > Scheme > Edit Scheme...

ステップ実行のためのoptimization変更

ls was compiled with optimization - stepping may behave oddly; variables may not be available.

Optimization Level
BasicじゃなくてAllにしないと表示されない。

f:id:kubotti:20170120170909p:plain

メニューの
Product > Scheme > Edit Scheme...
で Run > Info > Build Configuration
をDebugに変更。

ls was compiled with optimization
のメッセージが消えた。

ソースコード書き換え

Linked lists - Learn C - Free Interactive C Tutorial

 // kubotti customize
    FTSENT *cur_temp = NULL;
    for (cur = list; cur; cur = cur->fts_link) {
        if (!strcmp(cur->fts_name, "kubotti.txt")){
            if(cur_temp == NULL){
                list = cur->fts_link;
                //free(cur);
            }else{
                cur_temp->fts_link = cur->fts_link;
            }
        }
        cur_temp = cur;
    }

code modification. not display if the name is kubotti.txt · kubotti/ls_cmd_mod@816e9a6 · GitHub

動作確認

~/Library/Developer/Xcode/DerivedData/file_cmds-boccc ....
にできたlsの実行ファイルを適当なディレクトリにコピー。

./ls /tmp/dir1

で実行。

kubotti.txt というファイルは表示しないlsコマンドができた。

f:id:kubotti:20170120231443p:plain

以上、終了。

(メモ)Visual Studio Code

最初にVisual Studio Codeを試した時のメモ。

.tar.gzを解凍して、Visual Studio Codeで開いた。
C/C++ extensionをインストールすることを推奨 と出たので、インストール。
ms-vscode.cpptools publisher:"Microsoft"

launch.json
"program": "enter program name, for example ${workspaceRoot}/a.out",

ソースの取得

https://opensource.apple.com/release/os-x-10105.html

file_cmds-242.tar.gz (Yosemite 10.10.5)
を解凍したけど、 にMakefileがない。

https://opensource.apple.com/source/file_cmds/file_cmds-188/ls/Makefile にはあるけど。

https://opensource.apple.com/source/file_cmds/file_cmds-212/Makefileがある中で一番数字が大きい。

ls/mac212% make
Makefile:16: /Library/Developer/CommandLineTools/Makefiles/CoreOS/ReleaseControl/BSDCommon.make: No such file or directory
make: *** No rule to make target `/Library/Developer/CommandLineTools/Makefiles/CoreOS/ReleaseControl/BSDCommon.make'.  Stop.

AWS Lambda エラーメモ1

作成したLambda + API Gatewayにアクセスしたら以下のエラー。

{"message":"Missing Authentication Token"}

Lambda管理画面のTriggers で、
既存のものを削除して作り直したら、エラーが出ずに正常に実行された。

エラー2

Lambda > Functions > funcName
Triggers
Add trigger

API Gatewayを選んで作成しようとしたら、以下のエラー。

There was an error creating the trigger: An integration is already present on this method

API nameは、プルダウンから選べるけど、そのままSubmitするとこのエラーが出るっぽい。
新しい名前で作ると、API Gatewayの管理画面で一覧に表示される。

とりあえずserverlessでpythonを試してみる

npmのインストール

なんかインストール方法が複数あるっぽいけど、
nodebrewというのを入れるのがよさげだったのでそれにしてみる。
(会社のmacにはanyenvというのが入っていた)

http://www.hirooooo-lab.com/entry/development/install-node

brew install nodebrew

nodebrew ls-remote
nodebrew install-binary v6.9.4

インストールに失敗した。

% nodebrew install-binary v6.9.4
Fetching: https://nodejs.org/dist/v6.9.4/node-v6.9.4-darwin-x64.tar.gz
Warning: Failed to create the file 
Warning: /Users/kubotad/.nodebrew/src/v6.9.4/node-v6.9.4-darwin-x64.tar.gz: No 
Warning: such file or directory

curl: (23) Failed writing body (0 != 941)
download failed: https://nodejs.org/dist/v6.9.4/node-v6.9.4-darwin-x64.tar.gz

ディレクトリを作ったらうまく行った。おかしい。

mkdir -p ~/.nodebrew/src

% nodebrew install-binary v6.9.4
Fetching: https://nodejs.org/dist/v6.9.4/node-v6.9.4-darwin-x64.tar.gz
######################################################################## 100.0%
Installed successfully

パスを通す。

echo 'export PATH=$PATH:~/.nodebrew/current/bin' >> ~/.zshrc
% source ~/.zshrc

% nodebrew use v6.9.4                                         
use v6.9.4

バージョン確認

% node -v
v6.9.4
% npm -v
3.10.10

https://nodejs.org/
から.pkgをダウンロードしてインストールでもいいような気がする。

anyenvのndenvの場合

インストール可能バージョンの一覧

ndenv install -l
# install
ndenv install v6.9.4
# installed list
ndenv versions
# switch
ndenv global v6.9.4

serverlessのインストール

# Install serverless globally
npm install serverless -g
% npm install serverless -g
/Users/kubotad/.nodebrew/node/v6.9.4/bin/serverless -> /Users/kubotad/.nodebrew/node/v6.9.4/lib/node_modules/serverless/bin/serverless
/Users/kubotad/.nodebrew/node/v6.9.4/bin/sls -> /Users/kubotad/.nodebrew/node/v6.9.4/lib/node_modules/serverless/bin/serverless
/Users/kubotad/.nodebrew/node/v6.9.4/bin/slss -> /Users/kubotad/.nodebrew/node/v6.9.4/lib/node_modules/serverless/bin/serverless

> serverless@1.5.0 postinstall /Users/kubotad/.nodebrew/node/v6.9.4/lib/node_modules/serverless
> node ./scripts/postinstall.js

/Users/kubotad/.nodebrew/node/v6.9.4/lib
└─┬ serverless@1.5.0 
  ├─┬ agent-base@2.0.1 
  │ └── semver@5.0.3 
  ├── ansi-regex@2.0.0 
  ├── ansi-styles@2.2.1 
  ├─┬ archiver@1.2.0 
  │ └── async@2.1.4 
  ├── archiver-utils@1.3.0 
  ├── argparse@1.0.9 
  ├── async@1.5.2 
  ├─┬ aws-sdk@2.7.13 
  │ └── uuid@3.0.0 
  ├── balanced-match@0.4.2 
  ├── base64-js@1.2.0 
  ├─┬ bl@1.1.2 
  │ └── readable-stream@2.0.6 
  ├── bluebird@3.4.6 
  ├── brace-expansion@1.1.6 
  ├── buffer@4.9.1 
  ├── buffer-crc32@0.2.13 
  ├── buffer-shims@1.0.0 
  ├── capture-stack-trace@1.0.0 
  ├── caw@2.0.0 
  ├── chalk@1.1.3 
  ├── combined-stream@1.0.5 
  ├── commander@2.8.1 
  ├── component-emitter@1.2.1 
  ├── compress-commons@1.1.0 
  ├── concat-map@0.0.1 
  ├── cookiejar@2.0.6 
  ├── core-util-is@1.0.2 
  ├── crc32-stream@1.0.0 
  ├── create-error-class@3.0.2 
  ├── crypto-browserify@1.0.9 
  ├── debug@2.3.3 
  ├── decompress@4.0.0 
  ├── decompress-tar@4.1.0 
  ├── decompress-tarbz2@4.1.0 
  ├── decompress-targz@4.0.0 
  ├── decompress-unzip@4.0.1 
  ├── deep-extend@0.4.1 
  ├── delayed-stream@1.0.0 
  ├── download@5.0.2 
  ├── duplexer3@0.1.4 
  ├── encoding@0.1.12 
  ├─┬ end-of-stream@1.1.0 
  │ └── once@1.3.3 
  ├── escape-string-regexp@1.0.5 
  ├── esprima@2.7.3 
  ├── extend@3.0.0 
  ├── fd-slicer@1.0.1 
  ├── file-type@3.9.0 
  ├── filename-reserved-regex@1.0.0 
  ├── filenamify@1.2.1 
  ├── filesize@3.3.0 
  ├── form-data@1.0.0-rc3 
  ├── formidable@1.0.17 
  ├── fs-extra@0.26.7 
  ├── fs.realpath@1.0.0 
  ├── get-proxy@1.1.0 
  ├── get-stdin@5.0.1 
  ├── get-stream@2.3.1 
  ├── glob@7.1.1 
  ├── glob-all@3.1.0 
  ├── got@6.6.3 
  ├── graceful-fs@4.1.11 
  ├── graceful-readlink@1.0.1 
  ├── has-ansi@2.0.0 
  ├── https-proxy-agent@1.0.0 
  ├── iconv-lite@0.4.15 
  ├── ieee754@1.1.8 
  ├── inflight@1.0.6 
  ├── inherits@2.0.3 
  ├── ini@1.3.4 
  ├── is-absolute@0.1.7 
  ├── is-natural-number@2.1.1 
  ├── is-redirect@1.0.0 
  ├── is-relative@0.1.3 
  ├── is-retry-allowed@1.1.0 
  ├── is-stream@1.1.0 
  ├── isarray@1.0.0 
  ├── jmespath@0.15.0 
  ├── js-yaml@3.7.0 
  ├─┬ json-refs@2.1.6 
  │ └── commander@2.9.0 
  ├── jsonfile@2.4.0 
  ├── klaw@1.3.1 
  ├── lazystream@1.0.0 
  ├── lodash@4.17.2 
  ├── lowercase-keys@1.0.0 
  ├── methods@1.1.2 
  ├── mime@1.3.4 
  ├── mime-db@1.25.0 
  ├── mime-types@2.1.13 
  ├── minimatch@3.0.3 
  ├── minimist@1.2.0 
  ├─┬ mkdirp@0.5.1 
  │ └── minimist@0.0.8 
  ├── moment@2.17.0 
  ├── ms@0.7.2 
  ├── native-promise-only@0.8.1 
  ├── node-fetch@1.6.3 
  ├── node-status-codes@2.0.1 
  ├── normalize-path@2.0.1 
  ├── object-assign@4.1.0 
  ├── once@1.4.0 
  ├── path-is-absolute@1.0.1 
  ├── path-loader@1.0.1 
  ├── pend@1.2.0 
  ├── pify@2.3.0 
  ├── pinkie@2.0.4 
  ├── pinkie-promise@2.0.1 
  ├── prepend-http@1.0.4 
  ├── process-nextick-args@1.0.7 
  ├── punycode@1.3.2 
  ├── qs@2.3.3 
  ├── querystring@0.2.0 
  ├── rc@1.1.6 
  ├── readable-stream@2.2.2 
  ├── reduce-component@1.0.1 
  ├── replaceall@0.1.6 
  ├── rimraf@2.5.4 
  ├── sax@1.1.5 
  ├── seek-bzip@1.0.5 
  ├── semver@5.3.0 
  ├── semver-regex@1.0.0 
  ├── shelljs@0.6.1 
  ├── slash@1.0.0 
  ├── sprintf-js@1.0.3 
  ├── string_decoder@0.10.31 
  ├── strip-ansi@3.0.1 
  ├─┬ strip-dirs@1.1.1 
  │ └── get-stdin@4.0.1 
  ├── strip-json-comments@1.0.4 
  ├── strip-outer@1.0.0 
  ├── sum-up@1.0.3 
  ├─┬ superagent@1.8.4 
  │ ├── isarray@0.0.1 
  │ └── readable-stream@1.0.27-1 
  ├── supports-color@2.0.0 
  ├── tar-stream@1.5.2 
  ├── through@2.3.8 
  ├── timed-out@3.0.0 
  ├── traverse@0.6.6 
  ├── trim-repeated@1.0.0 
  ├── tunnel-agent@0.4.3 
  ├─┬ unbzip2-stream@1.0.10 
  │ ├── base64-js@0.0.8 
  │ └── buffer@3.6.0 
  ├── unzip-response@2.0.1 
  ├── uri-js@2.1.1 
  ├── url@0.10.3 
  ├── url-parse-lax@1.0.0 
  ├── util-deprecate@1.0.2 
  ├── uuid@2.0.3 
  ├── wrappy@1.0.2 
  ├── xml2js@0.4.15 
  ├─┬ xmlbuilder@2.6.2 
  │ └── lodash@3.5.0 
  ├── xtend@4.0.1 
  ├─┬ yargs@1.2.6 
  │ └── minimist@0.1.0 
  ├── yauzl@2.7.0 
  └── zip-stream@1.1.0 

https://serverless.com/
のトップページに載っていたコマンドを入力してみる。

serverless create --template aws-nodejs

% ll
total 24
drwxr-xr-x   5 kubotad  staff   170  1 12 14:47 ./
drwx------@ 10 kubotad  staff   340  1 12 01:10 ../
-rw-r--r--   1 kubotad  staff    86  1 12 01:10 .npmignore
-rw-r--r--   1 kubotad  staff   466  1 12 01:10 handler.js
-rw-r--r--   1 kubotad  staff  2410  1 12 01:10 serverless.yml

とりあえずインストールできた。

デプロイ

AWS IAMでアクセスキーを作成。

https://serverless.com/framework/docs/providers/aws/guide/credentials/

serverless config credentials --provider aws --key AKIAIOSFODNN7EXAMPLE --secret wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
% serverless deploy

 Error --------------------------------------------------
 
     ServerlessError: ServerlessError: User: arn:aws:iam
     is not authorized to perform: cloudformation:DescribeStackResources

https://github.com/serverless/serverless/issues/588

  Serverless Error ---------------------------------------
 
     An error occurred while provisioning your stack: ServerlessDeploymentBucket
     - API: s3:CreateBucket Access Denied.

kubotad_lambda_inline_policy - Inline policy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cloudformation:Describe*",
                "cloudformation:List*",
                "cloudformation:Get*",
                "cloudformation:PreviewStackUpdate"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "cloudformation:CreateStack",
                "cloudformation:UpdateStack",
                "cloudformation:DeleteStack"
            ],
            "Resource": "arn:aws:cloudformation:*:*:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "lambda:Get*",
                "lambda:List*",
                "lambda:CreateFunction"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "lambda:AddPermission",
                "lambda:CreateAlias",
                "lambda:DeleteFunction",
                "lambda:InvokeFunction",
                "lambda:PublishVersion",
                "lambda:RemovePermission",
                "lambda:Update*"
            ],
            "Resource": "arn:aws:lambda:*:*:function:${project}*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "iam:PassRole"
            ],
            "Resource": "arn:aws:iam::*:role/${project}*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "apigateway:GET"
            ],
            "Resource": "arn:aws:apigateway:*::/restapis"
        },
        {
            "Effect": "Allow",
            "Action": [
                "apigateway:*"
            ],
            "Resource": "arn:aws:apigateway:*::/restapis/GATEWAY_ID/*"
        }
    ]
}
  Serverless Error ---------------------------------------
 
     An error occurred while provisioning your stack: IamRoleLambdaExecution


     is not authorized to perform: iam:GetRole on resource:

IAM権限の設定でエラーが出て直らなかったので、
AdministratorAccess
にして
% serverless deploy を実行したら、エラーが出ずにデプロイできた。

↓のIAM設定にしたらデプロイできた。

AWSLambdaFullAccess - AWS Managed policy
IAMFullAccess - AWS Managed policy
AmazonS3FullAccess - AWS Managed policy
AmazonAPIGatewayInvokeFullAccess - AWS Managed policy
AmazonAPIGatewayAdministrator - AWS Managed policy
AWSLambdaExecute - AWS Managed policy
AWSCloudFormationReadOnlyAccess - AWS Managed policy
kubotad_lambda_inline_policy - Inline policy 

Python

chalice

chaliceというのを試してみる。

http://dev.classmethod.jp/cloud/aws/preview-the-python-serverless-microframework-for-aws/

GitHub - awslabs/chalice: Python Serverless Microframework for AWS

pyenv install 2.7.11
pyenv local 2.7.11
pyenv virtualenv 2.7.11 chalice_dev

pyenv version
pyenv local chalice_dev
pyenv version

pip install chalice
chalice new-project helloworld && cd helloworld
cat app.py

chalice deploy
is not authorized to perform: lambda:AddPermission on resource: arn:aws:lambda:us-west-2:

IAM設定が分からないので、Admin権限のを作成した。

% chalice deploy
Updating IAM policy.
Updating lambda function...
Regen deployment package...
Sending changes to lambda.
Lambda deploy done.
API Gateway rest API already found.
Deleting root resource id
Done deleting existing resources.
Deploying to: dev
https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/dev/

動いた。