- 投稿日:2019-02-28T23:32:38+09:00
AWSのIAMロールとポリシーの違い
■概要
・AWSのIAMとは?(Identity and Access Management)
AWSのリソースに紐付けることができる権限設定を行うサービスの事。
(AWSのリソースは、EC2,RDS,Lambda...etcといった全てのサービスで生成するものに必要な物となります)・IAMの4つの要素
IAMには「グループ」、「ユーザ」、「ロール」、「ポリシー」の4つの要素がある。
(グループとユーザについては別途機会があれば^^;)■結論
IAMロール(Role) = 「AWSのリソースに付与するもの」で、実態はIAMポリシーをグルーピングしたものIAMポリシー(policy) = 「AWSリソースにアクセスするための権限設定」で、AWSが最初から用意してくれているつまりポリシーはロールに内包されている物であり、ロールはAWSリソースに付与されるものである。
例えば、あるEC2には一つだけIAMロールが付与出来るが、そのロールに様々なポリシーを付与する事で、そのEC2は様々なAWSリソースにアクセスする事が出来るようになる。
(AWSCliコマンドから、S3バケットにアクセスしたり、Lambdaを実行したり出来る。)■詳細
・IAMロールの細かい話
- IAMロールは作成する際に、どのサービスで使うかを選択する必要がある。
(よく使われるサービスがEC2とLambdaなので、下記のキャプチャのように、上のほうにピックアップされている)
・IAMポリシーの細かい話
- IAMポリシーは、AWSが用意してくれているもの意外に、自作することも出来る(インラインポリシー)
(その際は、ビジュアルエディタでポチポチサービスを選んで作ることも、JSONを書いて作ることも出来る)
→これは、AWSが用意しているポリシーでは、細かい設定が仕切れない事や、対象リソースを絞ったポリシーを作る必要がある人の為。
→さらにロールに設定できるAWSのマネージメントポリシーは最大10個までしか付与できないため(インラインポリシーなら無限?に付与できる)■最後に
今回はAWSの最初によく躓く最初にIAM周りにふれてみました。
IAMグループは、さらにロールをグルーピング化した物で、IAMユーザはAWSにログインした時orプログラムに権限を渡すときに作るものです。
↑説明が雑なので、要望があれば別途書きます。
以上、フィードバックやご指摘等いただけると大変ありがたいです!!よろしくお願いいたします!!
- 投稿日:2019-02-28T23:23:54+09:00
[AWS]SAMを使ってLambdaを定期実行するHelloWorld
LambdaファンクションをCloudWatch Eventを使って定期実行してみたいと思います。
0. 環境
$ docker -v Docker version 18.09.2, build 6247962 $ python --version Python 3.7.0 $ pip --version pip 19.0.3 $ aws --version aws-cli/1.16.114 Python/3.7.0 Darwin/18.2.0 botocore/1.12.104 $ sam --version SAM CLI, version 0.11.0AWSCLIの設定(aws configure)がしてある前提で進めます。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-configure.html#cli-quick-configuration1. HelloWorld実行(開発準備)
1-1. テンプレ作成
$ sam init -r python3.7 -n my-app今回はpython3.7で開発します。
my-appというプロジェクト名で作成します。以下の通り、作成されます。
$ cd my-app $ tree . |-- README.md |-- event.json |-- hello_world | |-- __init__.py | |-- __pycache__ | | |-- __init__.cpython-37.pyc | | `-- app.cpython-37.pyc | |-- app.py | `-- requirements.txt |-- template.yaml `-- tests `-- unit |-- __init__.py |-- __pycache__ | |-- __init__.cpython-37.pyc | `-- test_handler.cpython-37.pyc `-- test_handler.py 5 directories, 12 files1-2. 必要ライブラリインストール
$ cd hello_world/ $ pip install -r requirements.txt -t build/ $ cp *.py build/ $ cd ..templete.yamlの以下の部分を書き換えてください
CodeUri: hello_world/↓
CodeUri: hello_world/build/1-3. Lambdaテスト実行
作成したeventファイルで実行します。
hello worldが出力されればOK
初回起動はDockerが立ち上がるのに時間がかかります。$ sam local invoke -e event.json 〜(略)〜 {"statusCode": 200, "body": "{\"message\": \"hello world\"}"}1-4. Lambdaローカルエンドポイント作成
以下コマンドでローカルにLambdaのエンドポイントが作成できます。
$ sam local start-lambda実行はCLIかSDKを使って行えます。
今回はCLIを使って動作確認しました。$ aws lambda invoke --function-name "HelloWorldFunction" --endpoint-url "http://127.0.0.1:3001" out.txt { "StatusCode": 200 } $ cat out.txt {"statusCode": 200, "body": "{\"message\": \"hello world\"}"}これで開発環境は整いました。
2. Lambdaデプロイ
2.1 template.yaml作成
https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Resources: HelloWorldFunction: Type: AWS::Serverless::Function Properties: CodeUri: hello_world/build Handler: app.lambda_handler Runtime: python3.6 Events: HelloWorld: Type: Schedule Properties: Schedule: cron(30 23 ? * MON-FRI *)2-2. パッケージ化
S3バケットがない場合は作ります
$ aws s3 mb s3://my-app-lambda make_bucket: my-app-lambda以下コマンドでパッケージ化したものをS3に設置
$ sam package --template-file template.yaml --output-template-file packaged.yaml --s3-bucket my-app-lambda Uploading to 614e5f60f81b1272edd607033afa55d8 965373 / 965373.0 (100.00%) Successfully packaged artifacts and wrote output template to file packaged.yaml. Execute the following command to deploy the packaged template aws cloudformation deploy --template-file <PATH>/packaged.yaml --stack-name <YOUR STACK NAME>2-3. デプロイ
$ sam deploy --template-file packaged.yaml --stack-name my-app --capabilities CAPABILITY_IAM Waiting for changeset to be created.. Waiting for stack create/update to complete Successfully created/updated stack - my-appAWSコンソールから,CloudFormation, Lambda, CloudWatchイベント を確認してみてください。
作成されているはずです。app.pyに
削除する際は、CloudFormationから削除すれば関連するサービスまとめて削除してくれます。
- 投稿日:2019-02-28T23:23:54+09:00
[AWS]SAMを使ったLambdaを定期実行するHelloWorld
LambdaファンクションをCloudWatch Eventを使って定期実行してみたいと思います。
0. 環境
$ docker -v Docker version 18.09.2, build 6247962 $ python --version Python 3.7.0 (default, Feb 28 2019, 22:25:31) [Clang 9.0.0 (clang-900.0.39.2)] $ pip --version pip 19.0.3 from /Users/Hiroki/.pyenv/versions/3.7.0/lib/python3.7/site-packages/pip (python 3.7) $ aws --version aws-cli/1.16.114 Python/3.7.0 Darwin/18.2.0 botocore/1.12.104 $ sam --version SAM CLI, version 0.11.0AWSCLIの設定(aws configure)がしてある前提で進めます。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-configure.html#cli-quick-configuration1. HelloWorld実行(開発準備)
1-1. テンプレ作成
$ sam init -r python3.7 -n my-app今回はpython3.7で開発します。
my-appというプロジェクト名で作成します。以下の通り、作成されます。
$ cd my-app $ tree . |-- README.md |-- event.json |-- hello_world | |-- __init__.py | |-- __pycache__ | | |-- __init__.cpython-37.pyc | | `-- app.cpython-37.pyc | |-- app.py | `-- requirements.txt |-- template.yaml `-- tests `-- unit |-- __init__.py |-- __pycache__ | |-- __init__.cpython-37.pyc | `-- test_handler.cpython-37.pyc `-- test_handler.py 5 directories, 12 files1-2. 必要ライブラリインストール
$ cd hello_world/ $ pip install -r requirements.txt -t build/ $ cp *.py build/ $ cd ..templete.yamlの以下の部分を書き換えてください
CodeUri: hello_world/↓
CodeUri: hello_world/build/1-3. Lambdaテスト実行
作成したeventファイルで実行します。
hello worldが出力されればOK
初回起動はDockerが立ち上がるのに時間がかかります。$ sam local invoke -e event.json 〜(略)〜 {"statusCode": 200, "body": "{\"message\": \"hello world\"}"}1-4. Lambdaローカルエンドポイント作成
以下コマンドでローカルにLambdaのエンドポイントが作成できます。
$ sam local start-lambda実行はCLIかSDKを使って行えます。
今回はCLIを使って動作確認しました。$ aws lambda invoke --function-name "HelloWorldFunction" --endpoint-url "http://127.0.0.1:3001" out.txt { "StatusCode": 200 } $ cat out.txt {"statusCode": 200, "body": "{\"message\": \"hello world\"}"}これで開発環境は整いました。
2. Lambdaデプロイ
2.1 template.yaml作成
https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Resources: HelloWorldFunction: Type: AWS::Serverless::Function Properties: CodeUri: hello_world/build Handler: app.lambda_handler Runtime: python3.6 Events: HelloWorld: Type: Schedule Properties: Schedule: cron(30 23 ? * MON-FRI *)2-2. パッケージ化
S3バケットがない場合は作ります
$ aws s3 mb s3://my-app-lambda make_bucket: my-app-lambda以下コマンドでパッケージ化したものをS3に設置
$ sam package --template-file template.yaml --output-template-file packaged.yaml --s3-bucket my-app-lambda Uploading to 614e5f60f81b1272edd607033afa55d8 965373 / 965373.0 (100.00%) Successfully packaged artifacts and wrote output template to file packaged.yaml. Execute the following command to deploy the packaged template aws cloudformation deploy --template-file <PATH>/packaged.yaml --stack-name <YOUR STACK NAME>2-3. デプロイ
$ sam deploy --template-file packaged.yaml --stack-name my-app --capabilities CAPABILITY_IAM Waiting for changeset to be created.. Waiting for stack create/update to complete Successfully created/updated stack - my-appAWSコンソールから,CloudFormation, Lambda, CloudWatchイベント を確認してみてください。
作成されているはずです。削除する際は、CloudFormationから削除すれば関連するサービスまとめて削除してくれます。
- 投稿日:2019-02-28T23:01:35+09:00
オリジナルKdB(科目検索)を作ってみよう -番外1- FaaS下準備編
これまでの記事
- オリジナルKdB(科目検索)を作ってみよう -1- Node.jsセットアップ編
- オリジナルKdB(科目検索)を作ってみよう -2- パース編
- オリジナルKdB(科目検索)を作ってみよう -3- データで遊ぶ編
- オリジナルKdB(科目検索)を作ってみよう -4- Express.jsでWEBアプリことはじめ編
- オリジナルKdB(科目検索)を作ってみよう -5- Express.jsでWEBアプリ整形編
- オリジナルKdB(科目検索)を作ってみよう -6- 本番環境Herokuにデプロイ編
この記事を読む前に
ある特定の人にしかわからない単語が出現する可能性が高いです。あらかじめご了承ください。
この記事での開発環境
- MacOS 10.14.3
- Visual Studio Code 1.31.1
- Node.js LTS 10.15.1
はじめに
「オリジナルKdB(科目検索)を作ってみよう」の番外編です。これまではExpress.jsは使わず、サーバレスなシステムを作っていきましょう。シリーズでやっていたようにExpress.jsでエンヤコラはやらずに、関数を作るだけで簡単にサービスを作ることができます。
FaaS について
IaaS,BaaS,PaaS,SaaSなどに連なるサービスの1つがFaaS(Function as a Service)です。関数のみを記述するだけで良く、サーバ周りの記述を省略できる画期的なサービスです。
「サーバ周りに関するコードを書かない → サーバを用意する必要がない」ことからサーバレスアーキテクチャと呼ばれます(縮めて「サーバレス」と呼ばれることが多いです)。
- lambda関数を用意する。
- FaaSにアップロードする。
たった2ステップで簡単です。しかも、サーバを持たないのでDDoS攻撃によってサーバが落ちることがありません。データベースに直接接続していないため「サーバに侵入されて個人情報が...!?」というケースもありません。しかもサーバを24時間365日稼働しているわけではありません。リクエストが来た時だけ稼動するのでコストを抑えることができます。
簡単・安全・安いがFaaSのウリです。
FaaSを提供しているサービス
FaaSを提供しているサービスはいくつかあります。
AWS lambda
AWS(Amazon Web Service)で提供されているFaaSです。
さすがAWSというだけあって、毎月100万リクエスト、400,000 GB-秒まで無料とめちゃめちゃ太っ腹です。Node.js以外にPython, C#(.NET Core), Go, Java, Rubyと多様な言語に対応しています。まず始めるならオススメしたいFaaSと言えます。また、AWSが提供する他のサービスとの連携に優れており「S3(AWSの提供するクラウドストレージ)にファイルをアップロードしたら自動的に圧縮する」ような処理を簡単に組み立てることができます。
Google Cloud Functions
GCP(Google Cloud Platform)で提供されているFaaSです。
こちらも200万リクエスト、計算時間100万秒まで無料と太っ腹。こちらはNode.js限定(Go, Pythonがベータ版)です。専用のライブラリを入れる必要がありますがlambda関数の書き方が簡潔であり、日本語のレファレンスが充実しています。GCPの他のサービスと連携しやすいのも利点です。GCPのサービスは欲しいところに欲しい説明をくれるので、初心者から上級者まで使いこなせるのがいいですね。
IBM Cloud Functions
IBM Cloud で提供されているFaaSです。
使ったことがないので料金体系がわかりませんが、見た感じとても安いです。何よりもNode10.XやSwift4.X, PHP 7.X, Python3.Xと、新しいバージョンに対応しているのが素晴らしいです。実行環境で最新の機能が使えるのが最高です。Zeit Now
爆速デプロイをウリにしているFaaSです。料金体系がわかりやすく、個人サイト程度の規模なら無料で使うことができます。課金をすれば激安定額なのに商業利用に耐えるスペックで利用できます。また、lambda関数をアップロード時に本番環境を想定したサーバに一旦保存されるので「本番にデプロイしたら不具合が起きた!!!」なんてことを事前に検証することができます。
とりあえず完全無料でFaaSを初めてみたいという方にはオススメです。
上記の他にもいくつもFaaSを提供しているサイトがあります。自分好みなサービスを見つけてがっつり使っていきましょう??
ところで今回すること → 下準備
Lambda系のサービスに共通する特徴にファイル入出力周りが安定しないことが挙げられます。そのため、これまで使っていた
fs
モジュールでのファイル読み込みは使わないように調整しましょう。参考記事 → AWS Lambdaでファイル入出力をしてみる
module.exports
したファイルはちゃんと読み込んでくれるので、CSVファイルに書かれている全ての情報をjavasctiptファイルに書き出しましょう。まずは必要なパッケージをインストールします。
$ npm install iconv-lite csvそしたら、以下のように
dump.js
を作ります。dump.jsconst fs = require('fs'); const iconv = require('iconv-lite') const parse = require('csv').parse; // CSVファイル(Shift_jis)を読み込んでパース const dataGet = () => { const text = fs.readFileSync("kdb.csv") const ret = iconv.decode( Buffer.from(text), "Shift_JIS"); const dataArray = [] parse(ret, (err, data) => { if (err) console.log(err.message) else { data.forEach( (element) => { dataArray.push(element) }); } }); return dataArray } // 配列をもらってJSON化 const dataToJson = async (dataArray) => { const dataJson = { subjects: [] } dataArray.forEach( (element) => { dataJson.subjects.push( { id: element[0], name: element[1], lessonType: element[2], credit: element[3], level: element[4], semester: element[5], period: element[6], place: element[7], teachers: element[8], summary: element[9], remarks: element[10], otherCourseStatus: element[11], otherCourseInfo: element[12], engName: element[13], engId: element[14], searchOption: element[15], timestamp: element[16], } ) }) return dataJson } // 即時関数でdata.jsを生成 (async () => { const data = await dataGet() const json = await dataToJson(data) const myJs = `const json = ${JSON.stringify(json)}; module.exports = json;` fs.writeFileSync("data.js", myJs) })()※async/awaitについて説明してると記事が爆発的に大きくなってしまうので割愛します。
async/awaitについての参考サイト(Promise
と一緒に覚えると楽です)実行して、新しく
data.js
が作られていることを確認しましょう。$ node dump.js $ ls dump.js kdb.csv package.json package-lock.json node_modules data.js
data.js
の中身をみればわかりますが、kdb.csv
の情報が全て書き出されていることがわかります。もしうまく書き出せていなかったら、ごめんなさい...コメントにお願いします。とりあえず今回はこの辺で
下準備だけで内容のない記事となってしまいましたが、次回からがっつりFaaSを使っていきますので許してください。
ちなみに、AWSとGCPの2つを触る予定です。
- 投稿日:2019-02-28T21:51:18+09:00
AWS Session Managerを使用して30分でSSHログインをやめることができた話 〜JAWS DAYS 2019〜
はじめに
JAWS DAYS 2019に初めて参加してきました!!
すごい盛り上がりで、約2000人が参加されたそうです!キャンセル待ちも多数いたとか!!!
朝から参加しましたけど、内容が濃すぎて後半は頭がパンクしておりました…
自分が参加したセッションの中でも特に多くの聴講者がいたと感じたのは、EKS、CI/CDでした。
EKSは皆さん注目しているんでしょうね!弊社も本番環境docker化計画で密かに検討中です!JAWS DAYS 2019とは?
JAWS DAYS 2019 資料まとめタイトルと注目のサービスが違うじゃん…
そうなんです。ですが、今回はタイトルにある通りAWS Session Managerについてお話しようと思っております。
JAWS DAYS 2019でもAWS Session Managerのセッションがありました。
弊社の環境では、踏み台サーバを経由してEC2インスタンスにSSHログインする、という流れになっていたのですが、セッションのタイトルに 1日でSSHをやめることができた話 と書いてあるのを見つけ、すぐに 僕が作った最強のタイムテーブル に追加しました。セッションの資料:1日でSSHをやめることができた話 ~AWS Systems Manager Session Manager 導入と運用Tips~
セッションを聞いてみて
- SSHログインが不要
- 踏み台サーバが不要で余計なEC2インスタンスが減らせる!
- 公開鍵・秘密鍵の管理が不要!
- SSHのインバウンドポートが不要
- IAMで一元管理できる
- 人が増えてもサクッと追加できる!
- コンソールでの実行履歴が残せる
- S3 or CloudWatchLogsに送れる!
- CloudWtachLogs→lambdaとかでSlackに通知もできる!
マジかよ…メリットしかないやんけ…
というわけで、すぐにStaging環境で試してみました!
試した結果
1日というか、 30分 でシェルアクセスが出来ました!!!
登壇者の方も「1日と言っていますが、実際かかったのは3時間くらいです。」と仰っていましたが、それ以上の簡単さでした!というわけで、自分が設定した手順を説明します。
手順
- EC2に割り当てられているロールに AmazonEC2RoleforSSM をアタッチする
以上でした。
え…?マジで…?
実際に最小限これで出来ました。本当はよりセキュアにする設定もあるのですが、とりあえずお試しなのでよしとします。
本来の手順であれば、
- EC2にSSMエージェントをインストール
- IAMインスタンスプロファイルロールの作成
- EC2に上記のロールを割り当てる
- その他、よりセキュアな設定
とするのですが、弊社の環境はElasticBeanstalkを使用して、オートスケールするようにしています。
EC2にはすでに専用のロールが設定されており、そこに AmazonEC2RoleforSSM をアタッチしました。
また、SSMエージェントは2017年9月以降のAmazon Linux AMI に標準インストールされています。そのため、たった1ステップでインスタンスにシェルアクセスができるようになったというわけです!
(セキュアな設定…?Staging環境だから大丈夫!!)それだけで30分はかかりすぎでしょ…
ポリシーをアタッチしてもすぐに反映されてなくて…色々調べてから戻って来たら表示されてて…
今後の予定
Staging環境でしばらく使ってみて、問題がなければセキュアな設定をしたのち、本番環境にも適用しようと思います!
おわりに
JAWS DAYS 2019に行けてとてもよかったです!!
運営の皆さま、登壇者の皆さま、スポンサーの皆さま、本当にありがとうございました!!
この流れで頑張ってEKSを使って本番環境docker化していきたいと思います!!
- 投稿日:2019-02-28T18:23:06+09:00
AWS Cloud9の標準Dockerイメージからコンテナを起動しようとするとExited (1)となる
AWS Cloud9で新規作成した環境に標準で用意されているDockerイメージを使ってみようとしたが上手くいかず調査したときのメモ。
AWS Cloud9の環境にはDockerが既定でインストールされており、下記の4つのイメージが標準で作成されている。
これでコンテナを作って使えないかと考えた。ec2-user:~/environment $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE lambci/lambda python2.7 b92d1404520d 3 weeks ago 951MB lambci/lambda nodejs6.10 6d5686f02fe2 3 weeks ago 996MB lambci/lambda nodejs4.3 ce68cbe2ecf8 3 weeks ago 945MB lambci/lambda python3.6 659e6b066789 3 weeks ago 1.08GBしかし、runコマンドでイメージからコンテナを起動しようとすると、立ち上がってすぐにExited (1)となりコンテナが落ちてしまう。
ec2-user:~/environment $ docker run -itd b92d1404520d 7cc7c4396751e98e3f6ec1761041d0ed3f978fe5b7a5db57cb6f70d59b825292 ec2-user:~/environment $ docker run -itd 6d5686f02fe2 86e6cb64fa4a6af7640bb3158f0cbb3cf163bc40188e7f1ff3c717265113e50a ec2-user:~/environment $ docker run -itd ce68cbe2ecf8 f9ea26de0f5edd86a0e7c413b979a34dd7ae69c5346f92c694bd1d1f29501fc0 ec2-user:~/environment $ docker run -itd 659e6b066789 a32d9cf3042cbdf0a627fc445e3c39db7ea443ff624f5fd9d405f0edeab91449 ec2-user:~/environment $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a32d9cf3042c 659e6b066789 "/var/lang/bin/pytho…" 10 seconds ago Exited (1) 3 minutes ago keen_galileo f9ea26de0f5e ce68cbe2ecf8 "/usr/local/lib64/no…" 10 seconds ago Exited (1) 3 minutes ago reverent_tereshkova 86e6cb64fa4a 6d5686f02fe2 "/var/lang/bin/node …" 10 seconds ago Exited (1) 3 minutes ago vigorous_swanson 7cc7c4396751 b92d1404520d "/usr/bin/python2.7 …" 10 seconds ago Exited (1) 3 minutes ago infallible_ardinghelli--no-truncオプションでコンテナ起動時に実行されるCOMMANDを全文表示してみると、どうやらAWS Lambdaが関数を実行するときのコマンド実行シーケンスのように見える。(http://marcy.hatenablog.com/entry/2016/12/14/115953)
ec2-user:~/environment $ docker ps -a --no-trunc CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a32d9cf3042c(略) 659e6b066789 "/var/lang/bin/python3.6 /var/runtime/awslambda/bootstrap.py" 7 minutes ago Exited (1) 7 minutes ago keen_galileo f9ea26de0f5e(略) ce68cbe2ecf8 "/usr/local/lib64/node-v4.3.x/bin/node --expose-gc --max-executable-size=160 --max-semi-space-size=150 --max-old-space-size=2547 /var/runtime/node_modules/awslambda/index.js" 7 minutes ago Exited (1) 7 minutes ago reverent_tereshkova 86e6cb64fa4a(略) 6d5686f02fe2 "/var/lang/bin/node --expose-gc --max-executable-size=160 --max-semi-space-size=150 --max-old-space-size=2547 /var/runtime/node_modules/awslambda/index.js" 7 minutes ago Exited (1) 7 minutes ago vigorous_swanson 7cc7c4396751(略) b92d1404520d "/usr/bin/python2.7 /var/runtime/awslambda/bootstrap.py" 8 minutes ago Exited (1) 8 minutes ago infallible_ardinghellidocker logsでログを見てみる。
これは明らかにAWS Lambda関数の実行に失敗したときのエラー。ec2-user:~/environment $ docker logs a32d9cf3042c START RequestId: 010a633a-xxxx-xxxx-xxxx-xxxxxxxxxxxx Version: $LATEST Unable to import module 'lambda_function': No module named 'lambda_function' END RequestId: 010a633a-xxxx-xxxx-xxxx-xxxxxxxxxxxx REPORT RequestId: 010a633a-xxxx-xxxx-xxxx-xxxxxxxxxxxx Duration: 1 ms Billed Duration: 100 ms Memory Size: 1536 MB Max Memory Used: 19 MB {"errorMessage": "Unable to import module 'lambda_function'"} ec2-user:~/environment $ docker logs f9ea26de0f5e START RequestId: 6da74752-xxxx-xxxx-xxxx-xxxxxxxxxxxx Version: $LATEST Unable to import module 'index': Error at Function.Module._resolveFilename (module.js:325:15) at Function.Module._load (module.js:276:25) at Module.require (module.js:353:17) at require (internal/module.js:12:17) END RequestId: 6da74752-xxxx-xxxx-xxxx-xxxxxxxxxxxx REPORT RequestId: 6da74752-xxxx-xxxx-xxxx-xxxxxxxxxxxx Duration: 9.35 ms Billed Duration: 100 ms Memory Size: 1536 MB Max Memory Used: 22 MB {"errorMessage":"Cannot find module '/var/task/index'","errorType":"Error","stackTrace":["Function.Module._load (module.js:276:25)","Module.require (module.js:353:17)","require (internal/module.js:12:17)"]} ec2-user:~/environment $ docker logs 86e6cb64fa4a START RequestId: 64047b49-xxxx-xxxx-xxxx-xxxxxxxxxxxx Version: $LATEST Unable to import module 'index': Error at Function.Module._resolveFilename (module.js:469:15) at Function.Module._load (module.js:417:25) at Module.require (module.js:497:17) at require (internal/module.js:20:19) END RequestId: 64047b49-xxxx-xxxx-xxxx-xxxxxxxxxxxx REPORT RequestId: 64047b49-xxxx-xxxx-xxxx-xxxxxxxxxxxx Duration: 9.66 ms Billed Duration: 100 ms Memory Size: 1536 MB Max Memory Used: 27 MB {"errorMessage":"Cannot find module '/var/task/index'","errorType":"Error","stackTrace":["Function.Module._load (module.js:417:25)","Module.require (module.js:497:17)","require (internal/module.js:20:19)"]} ec2-user:~/environment $ docker logs 7cc7c4396751 START RequestId: cc72da4b-xxxx-xxxx-xxxx-xxxxxxxxxxxx Version: $LATEST Unable to import module 'lambda_function': No module named lambda_function END RequestId: cc72da4b-xxxx-xxxx-xxxx-xxxxxxxxxxxx REPORT RequestId: cc72da4b-xxxx-xxxx-xxxx-xxxxxxxxxxxx Duration: 0 ms Billed Duration: 100 ms Memory Size: 1536 MB Max Memory Used: 14 MB {"errorMessage": "Unable to import module 'lambda_function'"}どうやら私が使おうとしていたDockerイメージは、AWS Cloud9の本来の機能としてAWS Lambda関数の作成、テスト、デプロイを行う際に使用されるイメージで、正規の使い方ではないことをしようとしていたためエラーで落ちてしまっていた、ということでした。
https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/tutorial-lambda.html
結論として、Cloud9上でDockerを利用したい場合は、外部からpullするか、いちからbuildしましょう。
- 投稿日:2019-02-28T17:07:34+09:00
なる早でslackのスラッシュコマンドを作ってみる
はじめに
Serverless Framework
使えば割と簡単にスラッシュコマンド作れるのでは?と思いどれくらいで作成できるのか試してみました。
あんまりいいアイディアが出てこなかったので三角関数の値を返すスラッシュコマンドを作ろうと思います。/tri-func sin 30 0.5 /tri-func cos 60 0.5 /tri-func tan 45 1.0こんな感じで(
sinh
とかconh
がないのは勘弁)APIを作る
プロジェクトを作成
$ mkdir <project> && cd <project> $ sls create -t aws-python3 -n tri-func$ tree . ├── handler.py └── serverless.ymlpipenvの導入
標準の
math
ライブラリを使用してもいいのですが最近serverless-python-requirements
のdockerizePip
という依存関係があるライブラリをAmazonLinuxのDockerImageからビルドしてくれるものがあると知ったので、今回はnumpy
を使用して三角関数の値を返します。
今回はpipenv
とserverless-python-requirements
を使用してライブラリを使用します。pipenvで仮想環境を作り
numpy
をインストールする$ pipenv install --python 3.6.5 $ pipenv install numpyserverless-python-requirementsのインストール
$ sls plugin install -n serverless-python-requirementsserverless.ymlを編集
profile
を指定しない場合はdefault
が使用されますserverless.ymlservice: tri-func provider: name: aws runtime: python3.6 stage: stg region: ap-northeast-1 profile: <hogehoge> #profileが複数あるので指定する functions: get: handler: handler.get_tri events: #APIGatewayの設定 - http: GET / plugins: - serverless-python-requirements custom: pythonRequirements: usePipenv: true # pipenvを使用する dockerizePip: non-linux # amazonlinuxでビルドするhandler.pyを編集
handler.pyimport json import numpy as np def get_tri(event, context): # event['multiValueQueryStringParameters']['text']にコマンドの引数が入ってくる text = event['multiValueQueryStringParameters']['text'][0] text = text.split() try: tri = text[0] theta = int(text[1]) if tri == 'sin': result = np.sin(np.pi*theta/180) elif tri == 'cos': result = np.cos(np.pi*theta/180) elif tri == 'tan': result = np.tan(np.pi*theta/180) else : result = 'エラー' except Exception as e: result = 'エラー' body = { 'text': '結果: {}'.format(result), } response = { 'statusCode': 200, 'isBase64Encoded': False, 'headers': {'Content-Type': 'application/json'}, 'body': json.dumps(body) } return responseデプロイ
$ sls deploy -v Serverless: Stack update finished... Service Information service: tri-func stage: stg region: ap-northeast-1 stack: tri-func-stg resources: 9 api keys: None endpoints: # URLをメモっておく GET - https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/stg functions: get: tri-func-stg-get layers: Noneデプロイを行うとエンドポイントが表示されるのでメモしておく
Slackでスラッシュコマンドを登録する
Slack > 管理 > カスタムインテグレーション > Slash > 設定を追加 からCommands からスラッシュコマンドを作成する
デプロイした際に表示されたエンドポイントをURLにペーストする
そして作成!スラッシュコマンドを使ってみる
成功ですね(桁は許して)
結局どれくらいかかった?
Serverless Framework
の環境が整っていればおそらく10分程度でスラッシュコマンドが作れるのではないでしょうか。
ちなみにこの記事を書きながら作成していたので私は約1時間くらいでした。
- 投稿日:2019-02-28T16:03:35+09:00
LaravelアプリケーションをAWS上のDockerで動かす
概要
LaravelのアプリケーションをAWS上のDockerで動かすための環境を構築します。
具体的には、以下を行います。
- コンテナを構築するためのDockerfileを作成する
- ECRリポジトリの作成 → AWS CLIで作成
- 1.で作成したDockerイメージをECRにをpushする
- ECSの環境構築 → マネジメントコンソールから作成
前提条件
- AWS CLIがインストールがインストールされていること
コンテナを構築
php
とnginx
の2つのコンテナを構築します。Dockerfileは、それぞれ下記の通りです。phpコンテナのDockerfile
必要なソースコードをコンテナ内にコピーし、依存ライブラリのインストールを行なっています。
FROM php:7.2.10-fpm-alpine COPY . . WORKDIR /var/www/html RUN set -x && \ apk update && \ apk add --no-cache libxml2 libxml2-dev curl curl-dev autoconf $PHPIZE_DEPS && \ docker-php-ext-install opcache mysqli pdo pdo_mysql xml mbstring curl session tokenizer json && \ curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer && \ composer global require hirak/prestissimo && \ composer install && \ chmod -R a+w storage/ bootstrap/cache COPY ./docker/php/config/php.ini /usr/local/etc/php/php.ini COPY ./docker/php/config/docker-php-ext-opcache.ini /usr/local/etc/php/conf.d/docker-php-ext-opcache.ininginxのDockerfile
default.conf
の設定を行なっています。
public
ディレクトリ配下は、nginx
コンテナに配置しています。FROM nginx:1.15.5-alpine ADD ./docker/nginx/config/default.conf /etc/nginx/conf.d/default.conf RUN mkdir -p /var/www/html/public ADD ./public/ /var/www/html/public
.dockerignore
の追加Dockerのイメージを小さくするために、
.dockerignore
を追加します。
node_modules
のような容量が大きいものは追加しておく方がいいと思います。
.dockerignore
については、下記の記事に詳しく説明されていますので載せておきます。
.dockerignore アンチパターンECRにDockerイメージをpushする
ECRとは
ECR(Amazon Elastic Container Registry)は、Dockerのコンテナイメージを保存しておくためのレジストリサービスです。ECRに保存したコンテナイメージは、Amazon ECSへのデプロイが可能であったり、他の AWS サービスと簡単に連携することができます。
事前準備
AWS CLIを使用して、ECR用のプロファイルを作成します。
$ aws configure --profile ecrリポジトリ作成
php
とeginx
の2つのリポジトリを作成します。$ aws ecr create-repository --repository-name php --profile ecr $ aws ecr create-repository --repository-name nginx --profile ecrマネジメントコンソールで作成する場合は、以下の通りです。
Amazon ECR
>Repositories
を選択し、リポジトリの作成
をクリックします。
リポジトリ名を入力し、
リポジトリの作成
をクリックして、リポジトリを作成します。
nginx/phpコンテナのビルド
上記で作成したリポジトリ名と同じになるように、dockerイメージ名を指定しビルドします。
タグにはlatest
としていますが、必要に応じて変更してください。$ docker build -t {AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/php:latest -f docker/php/Dockerfile . $ docker build -t {AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/nginx:latest -f docker/nginx/Dockerfile .以下の通りDockerイメージが作成されているはずです。
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE ************.dkr.ecr.ap-northeast-1.amazonaws.com/php latest e7cc55e81372 23 seconds ago 376MB ************.dkr.ecr.ap-northeast-1.amazonaws.com/nginx latest c9bfc2840cbc 3 minutes ago 18.2MBECRにログイン
ECRにログインする為のパスワードを取得します。
$ aws ecr get-login --region ap-northeast-1 --no-include-email --profile ecr以下のコマンドが表示されるので、全てコピペし、
docker login
でログインします。docker login -u AWS -p password https://{AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com
Login Succeeded
と表示されればログイン成功です。
~/.docker/config.json
を確認するとauths
に追加されていることが確認できます。~/.docker/config.json"auths": { "{AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com": {} },ECRへDockerイメージをpush
上記で作成したリポジトリにDockerイメージをpushします。
$ docker push {AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/php:latest $ docker push {AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/nginx:latestECSの環境構築
セキュリティグループの作成
ECSを構築する前に、以下を実現するためのセキュリティグループを2つ作成します。
- インターネットからALBの 443/tcp に対するアクセス許可
- ALBからphpコンテナの 80/tcp に対するアクセス許可
ALBのセキュリティグループ
- 外部から 443/tcp へのアクセス許可
以降の手順で作成するALBを割り当てます。
ECSサービスのセキュリティグループ
- ALBのセキュリティグループから 80/tcp へのアクセス許可
ECSサービスのセキュリティグループとしてますが、実際にはECSでクラスターを作成する際にEC2インスタンスに割り当てるセキュリティグループです。
ALBを作成する
通常のALB作成手順に従ってください。
セキュリティグループは、上記で作成したALBのセキュリティグループを割り当てます。ALBを利用せずにECSをPublicサブネットに配置する場合は、作成する必要はありません。
これ以降、ECSの構築を行なっていきます。
タスクを定義する
コンテナの起動方法をタスクの定義として登録します。
phpコンテナとnginxンテナの組み合わせを定義していきます。
Amazon ECS
>タスク定義
から、新しいタスク定義の作成
を選択します。
起動タイプは、EC2
を選択します。タスクとコンテナの定義の設定
項目 値 タスク定義名 sample-api タスクロール なし ネットワークモード default 補足:
タスクロールは、コンテナ内から他のサービスにアクセスするためのロール設定です。
ネットワークモードについては、下記の記事にわかりやすくまとめられていましたので、掲載します。
ECSでEC2インスタンスを利用する際のネットワークモードについて調べてみた | DevelopersIO次に、コンテナの定義で、phpコンテナとnginxコンテナを追加します。
phpコンテナを追加
項目 値 コンテナ名 php イメージ {AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/php:latest 作業ディレクトリ /var/www/html メモリ制限(MB) ハード制限 300(MB) nginxコンテナを追加
項目 値 コンテナ名 nginx イメージ {AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/nginx:latest メモリ制限(MB) ハード制限 300(MB) リンク php ポートマッピング tcp 80:80 以上で設定は完了です。
作成
を押下して、タスクの定義を作成します。ECSクラスタを作成する
Amazon ECS
>クラスター
から、クラスターの作成
を選択します。
クラスターテンプレートの選択
は、EC2 Linux + ネットワーキング
を使用します。インスタンスの設定
項目 値 クラスター名 sample-api-cluster EC2 インスタンスタイプ t2.micro プロビジョニングモデル スポット スポットインスタンスの配分戦略 最低価格 インスタンス数 1 Maximum bid price (per instance/hour) 10($) 補足:
スポットインスタンスは中断される可能性があります。中断できないアプリケーションに対しては、スポットインスタンスを使用しないことをお勧めします。
クラスターの作成 - Amazon Elastic Container Servicesshログインを可能とする場合、キーペアを指定している必要があります。
この場合、セキュリティグループで22番ポートも解放してください。ネットワーキング
VPCは、ALB作成で指定したVPC指定。
セキュリティグループは、作成済みのECSサービスのセキュリティグループを指定。コンテナインスタンス IAM ロール
デフォルトで選択されているecsInstanceRole
を指定。スポット群 IAM ロール
デフォルトで選択されているecsSpotFleetRole
を指定。以上で設定は完了です。
作成
を押下して、クラスタを作成します。
クラスタが作成されると、コンテナが起動するEC2インスタンスが作成されます。サービスを作成する
Amazon ECS
>クラスター
>サービスタブ
から、作成
を選択します。
項目 値 起動タイプ EC2 タスク定義 sample-api クラスタ sample-api-cluster サービス名 sample-api サービスタイプ REPLICA タスクの数 1 Elastic Load Balancing(オプション)
項目 値 ELB タイプ Application Load Balancer サービス用の IAM ロールの選択 デフォルトで選択されているecsServiceRoleを選択 ELB 名 作成したALBを選択 負荷分散用のコンテナ
nginx:80:80
を指定し、ELBへの追加
を選択。
ターゲットグループ名に、作成したALBに紐づくターゲットグループを選択
を選択。以上で、ECSの環境構築は完了です。
動作確認
作成したALBの
DNS名
にアクセスし、動作確認を行います。Fargateに移行
この記事で作成した環境をFargateに変更する手順を簡単にまとめました。
ECSのバックエンドをEC2からFargateに変更参考記事
下記を参考にさせていただきました。
【AWS】初めてのECR
LaravelアプリケーションをローカルでもAWSでもDockerで動かす
- 投稿日:2019-02-28T13:53:49+09:00
sam-cliを使ってKotlinでlambdaを書いた話
概要
最近流行りのsam-cliを使って、Kotlinでlambdaを書いてみました。
今回書いたのは簡単なGETとPOSTの処理になります。
完成物はこちら環境
- Kotlin1.3.20
- Docker for Mac
- SAM-CLI
開発
開発環境構築
sam-cliのインストール〜パッケージ作成
- brew tap aws/tap
- brew install aws-sam-cli
- sam init --runtime java8
mavenにKotlinの依存関係等の追記
- dependenciesに以下のライブラリを追加します。
- kotlin-stdlib-jdk8
- kotlin-test-junit
- pluginに以下のプラグインを追記します。
- maven-shade-plugin
- sourceDirectory, testSourceDirectoryのpathをsrc/main/kotlin, src/test/kotlinに変更する。
完成品はこちら
javaのソースをKotlinに変換
こちらはintellijを使っていれば、自動でjavaからKotlinに変更することができます。
最初の動作確認
$ mvn package $ sam local start-apiこれでlocal環境でlambdaが立ち上がり、localhostでアクセスできるようになるのでまずは動くことを確認します。
最初はlocalhost:3000/hello
でHello World
になるはずです。POST用のlambdaの作成
今回は新たにリクエストボディに人の名前を詰めると、レスポンスにそれを含めてHello Worldを返すAPIを作成します。
受け取るRequestのclassの作成
今回はbodyに以下のようなJsonを渡します。
{ "firstName": "太郎", "lastName": "山田" }次にリクエストを受け取るためのクラスを作成します。
ターミナルにて、以下のコマンドを実行するとlambdaが受け取るeventのjsonが取得できるので、それに沿ってクラスを作ります。$ sam local generate-event apigateway aws-proxy --method POST{ "body": "eyJ0ZXN0IjoiYm9keSJ9", "resource": "/{proxy+}", "path": "/path/to/resource", "httpMethod": "POST", "isBase64Encoded": true, "queryStringParameters": { "foo": "bar" }, "pathParameters": { "proxy": "/path/to/resource" }, "stageVariables": { "baz": "qux" }, "headers": { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Encoding": "gzip, deflate, sdch", "Accept-Language": "en-US,en;q=0.8", "Cache-Control": "max-age=0", "CloudFront-Forwarded-Proto": "https", "CloudFront-Is-Desktop-Viewer": "true", "CloudFront-Is-Mobile-Viewer": "false", "CloudFront-Is-SmartTV-Viewer": "false", "CloudFront-Is-Tablet-Viewer": "false", "CloudFront-Viewer-Country": "US", "Host": "1234567890.execute-api.us-east-1.amazonaws.com", "Upgrade-Insecure-Requests": "1", "User-Agent": "Custom User Agent String", "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", "X-Forwarded-For": "127.0.0.1, 127.0.0.2", "X-Forwarded-Port": "443", "X-Forwarded-Proto": "https" }, "requestContext": { "accountId": "123456789012", "resourceId": "123456", "stage": "prod", "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", "requestTime": "09/Apr/2015:12:34:56 +0000", "requestTimeEpoch": 1428582896000, "identity": { "cognitoIdentityPoolId": null, "accountId": null, "cognitoIdentityId": null, "caller": null, "accessKey": null, "sourceIp": "127.0.0.1", "cognitoAuthenticationType": null, "cognitoAuthenticationProvider": null, "userArn": null, "userAgent": "Custom User Agent String", "user": null }, "path": "/prod/path/to/resource", "resourcePath": "/{proxy+}", "httpMethod": "POST", "apiId": "1234567890", "protocol": "HTTP/1.1" } }続いてこのJsonに対応するクラスを作っていきます。
class Request { lateinit var body: String | } data class Person(val firstName: String, val lastName: String)Requestクラスの方は、
RequestHandler
を継承したクラスでlambdaの関数を作成する場合、空のコンストラクタがないとパースできないので、今回は通常のclassにしています。
また、リクエストボディに関しては、Jsonではなく文字列で受け取るので、RequestクラスではString型で定義します。
今回はbody以外使わないので、classにはbody以外持たせていません。lambdaの関数の実装
まずはJsonをパースするために
jackson-module-kotlin
をpom.xmlのdependencyに追記します。
続いていよいよ関数を実装していきます。
基本的な流れは自動生成されるgetのものと同様ですが、最初にリクエストボディをパースします。
実際のコードは以下の通りです。class PostApp : RequestHandler<Request, GatewayResponse> { override fun handleRequest(input: Request, context: Context?): GatewayResponse { val headers = HashMap<String, String>() headers["Content-Type"] = "application/json" headers["X-Custom-Header"] = "application/json" val mapper = jacksonObjectMapper() val person = mapper.readValue<Person>(input.body) return try { val pageContents = this.getPageContents("https://checkip.amazonaws.com") val output = String.format("{ \"message\": \"hello %s\", \"location\": \"%s\" }", person.lastName, pageContents) GatewayResponse(output, headers, 200) } catch (e: IOException) { GatewayResponse("{}", headers, 500) } } @Throws(IOException::class) private fun getPageContents(address: String): String { val url = URL(address) BufferedReader(InputStreamReader(url.openStream())).use { br -> return br.lines().collect(Collectors.joining(System.lineSeparator())) } } }動作確認
$ mvn package $ sam local start-apiこれらを実行し、今回自分で作成したlambdaのエンドポイントを叩いてみます。
$ curl -X POST -d '{"firstName": "山田", lastName: "太郎"}' https://127.0.0.1:3000これで期待したレスポンスが返ってくれば成功です!
最後に
「javaでかけるんだからKotlinでもかけるっしょ」の精神で書いてみました。
ただ書いてみて思うのは、あえてKotlinで書く必要性がそこまでなかったのではないだろうか。。。というものでした。
個人の趣味とか、会社で使うlambdaの一つをお試しで、とかなら良いかもしれません。以上でsam-cliを使ってKotlinでlambdaを書いた話は終わりになります。
ありがとうございました。
- 投稿日:2019-02-28T13:39:46+09:00
AWS-CDK for TypeScriptで色んなサービスをデプロイする
はじめに
皆様はAWSのサービスをデプロイするのをどうされていますか?
- コンソール画面からGUIで操作して…
- AWS-CLIで利用して…
- CloudFormationのテンプレートファイルを書いて…
- TerraformやServerlessFrameworkなどの構成管理ツールを使って…
などの方法があると思います。
デプロイするサービスが多くなればなるほど、構成管理ツールを用いたほうが管理コストがかからなくなるので良いですよね。
どのサービスをどれだけ、どのサービスと紐づけているのかをソースコードベースで確認することができます。
また不必要なサービスを減らすことができるのも利点の一つかと思います。今回は
awslabs
がOSSとして開発しているAWS-CDK
を紹介していこうと思います。AWS-CDKとは?
AWS-CDK(Cloud Development Kit)はCloudForamationのテンプレートファイルを、TypeScriptやJavaScript、Javaなどで書くことができるフレームワークです。
CloudForamationのテンプレートファイルはJSONまたはYAMLで書く必要があり、馴染みのないエンジニアにとっては学習コストが高く感じることがあると思います。
AWS-CDKではtsファイルやjsファイルをビルドするとCloudFormationのYAMLファイルが生成されます。
リリースされたのは去年の夏頃で、OSSで開発が進められています。(2019/02/28時点の最新バージョンは0.24.1
)
ただまだ開発者プレビューという状態なので、「これから大きな変更があるかもしれないよ」とドキュメント内でも書かれています。この記事ではTypeScriptでの書き方を紹介していきます。
この記事で紹介したソースコードなどは こちらのGithubリポジトリにpushしています。こちらも合わせてご確認ください。前提条件
- Node.js >= 8.11.x
- TypeScript => 2.7
- AWSのCredentailの設定(参考)(AWS-CLIの初期設定ができていたらOK)
インストール
$ npm i -g aws-cdk $ cdk --version 0.24.1 (build 67fcf6d)初期設定
$ mkdir hello-cdk $ cd hello-cdk $ cdk init app --language=typescriptコマンド
// デプロイ $ cdk deploy // スタックを指定してデプロイ $ cdk deploy ${StackName} // CloudFormationのテンプレートファイル生成 $ cdk synth // CloudFormationのテンプレートファイル生成してファイルに書き出す $ cdk synth --output ./output // 差分を確認 $ cdk diff今回デプロイしていくサービス
- S3
- DynamoDB
- APIGateway
- Lambda
- IAM
- Cognito
S3
Install Package
$ npm i @aws-cdk/aws-s3SourceCode
```ts
import cdk = require("@aws-cdk/cdk");
import s3 = require("@aws-cdk/aws-s3");export class CdkStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);/** * Create S3 bucket */ new s3.Bucket(this, id, { bucketName: "bucketName" })}
}
```
DynamoDB
Install Pakcage
$ npm i @aws-cdk/aws-dynamodbSourceCode
import cdk = require("@aws-cdk/cdk"); import dynamodb = require("@aws-cdk/aws-dynamodb"); export class CdkStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); /** * Create DynamoDB Table */ new dynamodb.Table(this, id, { tableName: "tableName", partitionKey: { name: "HashKey", type: dynamodb.AttributeType.String // String or Number or Binary }, sortKey: { name: "SortKey", type: dynamodb.AttributeType.String // String or Number or Binary } } ) } }
APIGateway & Lambda & IAM
Install Package
$ npm i @aws-cdk/aws-apigateway @aws-cdk/aws-lambda @aws-cdk/aws-iamSourceCode
Webアプリケーションからのリクエストを受け取るRESTの受け口としてAPIGatewayを立てます。
また、CORSとCognitoUserPool認証を有効にしています。
LambdaはDynamoDBへの権限をいくつか付与し、APIGatewayからinvokeされるようにしています。
import cdk = require("@aws-cdk/cdk"); import apigateway = require("@aws-cdk/aws-apigateway"); export class CdkStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); /** * Create APIGateway */ const api: apigateway.RestApi = new apigateway.RestApi(this, id, { restApiName: "apiName", description: "apiDescription" }); /** * Create APIGateway Authorizer * Cognito認証の設定 */ const apiAuthorizer: apigateway.CfnAuthorizer = new apigateway.CfnAuthorizer(this, id, { restApiId: api.restApiId, name: "authorizerName", identitySource: "method.request.header.Authorization", providerArns: ["cognitoArn"], type: "COGNITO_USER_POOLS" }); /** * Create Lambda Function */ const getHandler: lambda.Function = new lambda.Function(this, id, { functionName: "functionName", runtime: lambda.Runtime.NodeJS810, // Lambdaのランタイム code: lambda.Code.directory("resources"), // Lambdaのソースコードを置いているディレクトリ handler: index.handler, // Lambdaのハンドラー environment: { TZ: "Asia/Tokyo" // 環境変数 } }); /** * Create IAM Policy Statement */ const statement: iam.PolicyStatement = new iam.PolicyStatement().allow() .addActions( "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:Query", "dynamodb:Scan" ) .addResource( "DynamoDBTableARN" // 操作の対象となるDynamoDBTableのARN ); /** * Attach role to Lambda */ getHandler.addToRolePolicy(statement); /** * Add GET method to APIGateway */ const integration = new apigateway.LambdaIntegration(getHandler); const option: apigateway.MethodOptions = { authorizationType: apigateway.AuthorizationType.Cognito, authorizerId: authorizer.authorizerId } api.root.addMethod("GET", integration, option); /** * Active APIGateway CORS Setting * CORSの設定をするために OPTION メソッドを追加します */ const options = api.root.addMethod("OPTIONS", new apigateway.MockIntegration({ integrationResponses: [{ statusCode: "200", responseParameters: { "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'", "method.response.header.Access-Control-Allow-Origin": "'*'", "method.response.header.Access-Control-Allow-Credentials": "'false'", "method.response.header.Access-Control-Allow-Methods": "'OPTIONS,GET,PUT,POST,DELETE'", } }], passthroughBehavior: apigateway.PassthroughBehavior.Never, requestTemplates: { "application/json": "{\"statusCode\": 200}" } })); const methodResource = (options as cdk.Construct).node.findChild("Resource") as apigateway.CfnMethod; methodResource.propertyOverrides.methodResponses = [{ statusCode: "200", responseModels: { "application/json": "Empty" }, responseParameters: { "method.response.header.Access-Control-Allow-Headers": true, "method.response.header.Access-Control-Allow-Origin": true, "method.response.header.Access-Control-Allow-Credentials": true, "method.response.header.Access-Control-Allow-Methods": true, } }]; } }
Cognito
Install Package
$ npm i @aws-cdk/aws-cognitoSourceCode
import cdk = require("@aws-cdk/cdk"); import cognito = require("@aws-cdk/aws-cognito"); export class CdkStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); /** * Create Cognito UserPool */ const userPool: cognito.CfnUserPool = new cognito.CfnUserPool(this, id, { userPoolName: "UserPoolName", // パスワードポリシー policies: { passwordPolicy: { minimumLength: 8, requireLowercase: true, requireNumbers: true, requireUppercase: true, requireSymbols: false } }, // 必須の標準属性やカスタム属性 schema: [ { name: "email", attributeDataType: "String", required: true } ], // 自動検証する項目 autoVerifiedAttributes: ["email"], // Eメール検証メッセージの件名 emailVerificationSubject: "Your verification code", // Eメール検証メッセージの内容 emailVerificationMessage: "Your verification code is {####}" }); /** * Create Cognito UserPool Client */ new cognito.CfnUserPoolClient(this, id, { clientName:"UserPoolClientName", userPoolId: userPool.userPoolId }); }
まとめ
「TypeScriptからCloudFormationのYAMLが生成されるなんて素敵過ぎる!!!」と興奮気味な感じで色々触ってみましたが、実際最高でした。
YAMLファイルを書くのにあまり抵抗はないのですが、AWS-CDKで生成すると、自動で設定を保管してくれる部分もあったりするので、一からすべてを書かないといけないというわけではないです。
またドキュメントもまだまだ少なく、ドキュメント読むよりソースコード読んだほうが早い。みたいなことがあったりします。
前述したとおり、まだ開発者プレビューの段階ということなので、今後のアップデートをしっかり追って行くことが大事だと思います。
今後も他のサービスのデプロイを確認したりしていこうと思っています!
ではまた!!!
- 投稿日:2019-02-28T13:25:40+09:00
MastodonをAWS+オレオレ証明書で動かしてみる
概要
自分の勉強がてらAWSインスタンスにMastodonを設定してみる。SSL必須のようなのだが、恒常的に動かすつもりがないので、オレオレ証明書でとりあえず動かしてみる。当然ながら、このまま利用するのはセキュリティ的に問題なのでご承知頂きたい。
参考サイト
以下のサイトの情報を参考にした。
Dockerで雑にMastodonを起動する方法
AWSでMastodonインスタンスを作るまで。自分まとめ
今何かと話題のマストドン(mastodon)鯖を自分用に無料で立てる方法
Docker+MacでMastodonインスタンスをローカルで構築する
自己署名証明書でnginxをSSL化構築手順
1. AWSでEC2インスタンスを作成
手順は省略。
とりあえずOSはUbuntu18.04,インスタンスタイプはt2.medium,ボリュームサイズは20GBで設定。セキュリティグループはssh(22)とHTTPS(443)をインバウンドに設定しておく。2. スワップファイルの作成
インスタンスタイプはt2.micro程度だとメモリが足りないようなので、スワップファイルを作成する。ただし、dockerコンテナのbuildに無茶苦茶かかるので、buildまではインスタンスタイプを高くしておく手もある。
$ sudo fallocate -l 4G /swapfile $ sudo chmod 600 /swapfile $ sudo mkswap /swapfile $ sudo swapon /swapfile $ echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab3.ミドルウェアのインストール
必要なパッケージを入れていく。
$ sudo apt-get update $ sudo apt-get install -y python3-pip unzip docker.io nginx $ sudo pip3 install docker-compose4.Mastodonを設定する
MastodonをGithubから取得する。とりあえず、ホームディレクトリ直下へ。
バージョンによって出来ることの差が激しいので構築するバージョンを固定する。
作成時点で最新のtagであるv2.7.3に切り替える。$ git clone https://github.com/tootsuite/mastodon.git $ cd mastodon $ git checkout -b v2.7.3 refs/tags/v2.7.3ここで、永続化するためにdocker-compose.ymlの編集する例が多いが、v2.7.3では既に編集済みだったので、初期状態のままで大丈夫。
永続化用のディレクトリを作っておく。作成場所はdocker-compose.ymlと同階層。
$ mkdir postgres $ mkdir redisDockerイメージを作成する。インスタンスタイプによってはすごく時間がかかる。
$ docker-compose build
その間にSSLの設定用に秘密鍵とオレオレ証明書を作成する。
5.SSLの設定
オレオレ証明書の作成
opensslを使って証明書を作成する。Ubuntu18.04にはプレインストールされていたが、なければインストールする。
オレオレ証明書はオレオレ認証局(ca)から発行する。そのため、まずは認証局を作る必要がある。認証局の秘密鍵(ca.key)を作成してから、認証局の証明書(ca.crt)を作成する。
証明書の有効期限は10年 (3650日)とする。証明書作成は対話式なので好きな値を入れよう。未設定でも構わない。$ mkdir certs $ cd certs $ openssl genrsa -out ca.key 2048 $ openssl req -new -x509 -days 3650 -key ca.key -out ca.crt次にngnixに設定するオレオレサーバ証明書(mastodon.crt)を作成する。
秘密鍵(mastodon.key)を作って、その後認証局に依頼するための署名要求ファイル(mastodon.csr)を作成する。ここも対話式になるので、少なくともOUとCNは入力する。(ここではOU=example, CN=example.com)
最後に署名要求ファイルに認証局が署名してサーバ証明書(mastodon.crt)を作る。$ openssl genrsa -out mastodon.key 2048 $ openssl req -new -key mastodon.key -out mastodon.csr $ openssl x509 -req -days 3650 -CA ca.crt -CAkey ca.key -CAcreateserial -in mastodon.csr -out mastodon.crtnginxの設定
nginxの設定ファイルを編集する。先ほど作成したサーバ証明書と秘密鍵は
ssl_certificate,ssl_certificate_keyにパス付で指定する。$ sudo vim /etc/nginx/sites-enabled/default以下の内容に入れ替える。
/etc/nginx/sites-enabled/defaultmap $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 80; listen [::]:80; server_name localhost:3000; root /home/ubuntu/mastodon/live/public; # Useful for Let's Encrypt #location /.well-known/acme-challenge/ { allow all; } #location / { return 301 https://$host$request_uri; } } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name localhost:3000; ssl_protocols TLSv1.2; ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_certificate /home/ubuntu/mastodon/certs/mastodon.crt; ssl_certificate_key /home/ubuntu/mastodon/certs/mastodon.key; keepalive_timeout 70; sendfile on; client_max_body_size 80m; root /home/ubuntu/mastodon/live/public; gzip on; gzip_disable "msie6"; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_buffers 16 8k; gzip_http_version 1.1; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; add_header Strict-Transport-Security "max-age=31536000"; location / { try_files $uri @proxy; } location ~ ^/(emoji|packs|system/accounts/avatars|system/media_attachments/files) { add_header Cache-Control "public, max-age=31536000, immutable"; try_files $uri @proxy; } location /sw.js { add_header Cache-Control "public, max-age=0"; try_files $uri @proxy; } location @proxy { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; proxy_set_header Proxy ""; proxy_pass_header Server; proxy_pass http://127.0.0.1:3000; proxy_buffering off; proxy_redirect off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; tcp_nodelay on; } location /api/v1/streaming { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; proxy_set_header Proxy ""; proxy_pass http://127.0.0.1:4000; proxy_buffering off; proxy_redirect off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; tcp_nodelay on; } error_page 500 501 502 503 504 /500.html; }nginxを再起動する。
$ sudo systemctl start nginx6.再びMastodonの設定
以下のコマンドを2回打って、出力された文字列をどこかに記録しておく。
$ cd ~/mastodon $ docker-compose run --rm web rake secret次に環境設定ファイルを作る。テンプレートがあるのでそれをコピーして作成する。
$ cp .env.production.sample .env.production $ sudo vi .env.production以下のSECRET_KEY_BASE, OTP_SECRETに先ほどの文字列を設定する。
.env.production20 LOCAL_DOMAIN=localhost:3000 34 # Application secrets 35 # Generate each with the `RAILS_ENV=production bundle exec rake secret` task (`docker-compose run --rm web rake secret` if you use docker compose) 36 SECRET_KEY_BASE= 37 OTP_SECRET=Databaseを作成する。
$ docker-compose run --rm web rails db:migrateアセットを作成する。
$ docker-compose run --rm web rails assets:precompileMastodonのコンテナを起動する。docker-compose psできちんと立ち上がっているか確認しよう。
$ docker-compose up $ docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------------------- mastodon_db_1 docker-entrypoint.sh postgres Up (healthy) mastodon_redis_1 docker-entrypoint.sh redis ... Up (healthy) mastodon_sidekiq_1 /tini -- bundle exec sidekiq Up mastodon_streaming_1 /tini -- yarn start Up (unhealthy) 127.0.0.1:4000->4000/tcp mastodon_web_1 /tini -- bash -c rm -f /ma ... Up (unhealthy) 127.0.0.1:3000->3000/tcpMastodonに接続する
以上で完了。ChromeかEdgeあたりのWebブラウザで接続する。
FireFoxはオレオレ証明書のサイトは見れないので他のブラウザを使う。https://EC2インスタンスのパブリックDNS or パブリックIP/about
- 投稿日:2019-02-28T12:43:48+09:00
MastodonをAWS+オレオレ証明書で動かしてみる
概要
自分の勉強がてらAWSインスタンスにMastodonを設定してみる。SSL必須のようなのだが、恒常的に動かすつもりがないので、オレオレ証明書でとりあえず動かしてみる。当然ながら、このまま利用するのはセキュリティ的に問題なのでご承知頂きたい。
参考サイト
以下のサイトの情報を参考にした。
Dockerで雑にMastodonを起動する方法
AWSでMastodonインスタンスを作るまで。自分まとめ
今何かと話題のマストドン(mastodon)鯖を自分用に無料で立てる方法
Docker+MacでMastodonインスタンスをローカルで構築する
自己署名証明書でnginxをSSL化構築手順
1. AWSでEC2インスタンスを作成
手順は省略。
とりあえずOSはUbuntu18.04,インスタンスタイプはt2.medium,ボリュームサイズは20GBで設定。セキュリティグループはssh(22)とHTTPS(443)をインバウンドに設定しておく。2. スワップファイルの作成
インスタンスタイプはt2.micro程度だとメモリが足りないようなので、スワップファイルを作成する。ただし、dockerコンテナのbuildに無茶苦茶かかるので、buildまではインスタンスタイプを高くしておく手もある。
$ sudo fallocate -l 4G /swapfile $ sudo chmod 600 /swapfile $ sudo mkswap /swapfile $ sudo swapon /swapfile $ echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab3.ミドルウェアのインストール
必要なパッケージを入れていく。
$ sudo apt-get update $ sudo apt-get install -y python3-pip unzip docker.io nginx $ sudo pip3 install docker-compose4.Mastodonを設定する
MastodonをGithubから取得する。とりあえず、ホームディレクトリ直下へ。
バージョンによって出来ることの差が激しいので構築するバージョンを固定する。
作成時点で最新のbranchであるv2.7.3に切り替える。$ git clone https://github.com/tootsuite/mastodon.git $ cd mastodon $ git checkout v2.7.3ここで、永続化するためにdocker-compose.ymlの編集する例が多いが、v2.7.3では既に編集済みだったので、初期状態のままで大丈夫。
永続化用のディレクトリを作っておく。作成場所はdocker-compose.ymlと同階層。
$ mkdir postgres $ mkdir redisDockerイメージを作成する。インスタンスタイプによってはすごく時間がかかる。
$ docker-compose build
その間にSSLの設定用に秘密鍵とオレオレ証明書を作成する。
5.SSLの設定
オレオレ証明書の作成
opensslを使って証明書を作成する。Ubuntu18.04にはプレインストールされていたが、なければインストールする。
オレオレ証明書はオレオレ認証局(ca)から発行する。そのため、まずは認証局を作る必要がある。認証局の秘密鍵(ca.key)を作成してから、認証局の証明書(ca.crt)を作成する。
証明書の有効期限は10年 (3650日)とする。証明書作成は対話式なので好きな値を入れよう。未設定でも構わない。$ mkdir certs $ cd certs $ openssl genrsa -out ca.key 2048 $ openssl req -new -x509 -days 3650 -key ca.key -out ca.crt次にngnixに設定するオレオレサーバ証明書(mastodon.crt)を作成する。
秘密鍵(mastodon.key)を作って、その後認証局に依頼するための署名要求ファイル(mastodon.csr)を作成する。ここも対話式になるので、少なくともOUとCNは入力する。(ここではOU=example, CN=example.com)
最後に署名要求ファイルに認証局が署名してサーバ証明書(mastodon.crt)を作る。$ openssl genrsa -out mastodon.key 2048 $ openssl req -new -key mastodon.key -out mastodon.csr $ openssl x509 -req -days 3650 -CA ca.crt -CAkey ca.key -CAcreateserial -in mastodon.csr -out mastodon.crtnginxの設定
nginxの設定ファイルを編集する。先ほど作成したサーバ証明書と秘密鍵は
ssl_certificate,ssl_certificate_keyにパス付で指定する。$ sudo vim /etc/nginx/sites-enabled/default以下の内容に入れ替える。
/etc/nginx/sites-enabled/defaultmap $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 80; listen [::]:80; server_name localhost:3000; root /home/ubuntu/mastodon/live/public; # Useful for Let's Encrypt #location /.well-known/acme-challenge/ { allow all; } #location / { return 301 https://$host$request_uri; } } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name localhost:3000; ssl_protocols TLSv1.2; ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_certificate /home/ubuntu/mastodon/certs/mastodon.crt; ssl_certificate_key /home/ubuntu/mastodon/certs/mastodon.key; keepalive_timeout 70; sendfile on; client_max_body_size 80m; root /home/ubuntu/mastodon/live/public; gzip on; gzip_disable "msie6"; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_buffers 16 8k; gzip_http_version 1.1; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; add_header Strict-Transport-Security "max-age=31536000"; location / { try_files $uri @proxy; } location ~ ^/(emoji|packs|system/accounts/avatars|system/media_attachments/files) { add_header Cache-Control "public, max-age=31536000, immutable"; try_files $uri @proxy; } location /sw.js { add_header Cache-Control "public, max-age=0"; try_files $uri @proxy; } location @proxy { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; proxy_set_header Proxy ""; proxy_pass_header Server; proxy_pass http://127.0.0.1:3000; proxy_buffering off; proxy_redirect off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; tcp_nodelay on; } location /api/v1/streaming { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; proxy_set_header Proxy ""; proxy_pass http://127.0.0.1:4000; proxy_buffering off; proxy_redirect off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; tcp_nodelay on; } error_page 500 501 502 503 504 /500.html; }nginxを再起動する。
$ sudo systemctl start nginx6.再びMastodonの設定
以下のコマンドを2回打って、出力された文字列をどこかに記録しておく。
$ cd ~/mastodon $ docker-compose run --rm web rake secret次に環境設定ファイルを作る。テンプレートがあるのでそれをコピーして作成する。
$ cp .env.production.sample .env.production $ sudo vi .env.production以下のSECRET_KEY_BASE, OTP_SECRETに先ほどの文字列を設定する。
.env.production20 LOCAL_DOMAIN=localhost:3000 34 # Application secrets 35 # Generate each with the `RAILS_ENV=production bundle exec rake secret` task (`docker-compose run --rm web rake secret` if you use docker compose) 36 SECRET_KEY_BASE= 37 OTP_SECRET=Databaseを作成する。
$ docker-compose run --rm web rails db:migrateアセットを作成する。
$ docker-compose run --rm web rails assets:precompileMastodonのコンテナを起動する。docker-compose psできちんと立ち上がっているか確認しよう。
$ docker-compose up $ docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------------------- mastodon_db_1 docker-entrypoint.sh postgres Up (healthy) mastodon_redis_1 docker-entrypoint.sh redis ... Up (healthy) mastodon_sidekiq_1 /tini -- bundle exec sidekiq Up mastodon_streaming_1 /tini -- yarn start Up (unhealthy) 127.0.0.1:4000->4000/tcp mastodon_web_1 /tini -- bash -c rm -f /ma ... Up (unhealthy) 127.0.0.1:3000->3000/tcpMastodonに接続する
以上で完了。ChromeかEdgeあたりのWebブラウザで接続する。
なお、FireFoxはオレオレ証明のSSLは出来ないので他のブラウザを使う。https://EC2インスタンスのパブリックDNS or パブリックIP/about本格的に運用する時は、正式なドメイトとSSL証明書を取得しよう。
- 投稿日:2019-02-28T11:32:11+09:00
AWS Systems Manager のセッションマネージャーの小ネタ(Switchロールした際のログ表示、sudoの禁止)
はじめに
AWS Systems Manager のセッションマネージャーは、S3とCloudWatchLogsにログ出力できますが、Switchロールした場合は、どういった表示になるのか認識できてなかったので確認しました。ついでにsudoの禁止方法についても記載します。
Switchロールした場合のログ表示の確認
結論
Switchロール前のIAMユーザ名でセッションIDが表示されます。
実機確認
Switchロールする前のIAMユーザ(miyamoto)が表示されています。
CloudWatchLogsにも元のアカウントのIAMユーザ名がロギングされます。
Script started on 2019-02-28 01:47:39+0000 [?1034hsh-4.2# /usr/bin/ssm-session-logger /var/lib/amazon/ssm/i-030874ac1ad0d6f6d/sess ion/orchestration/miyamoto-08d0033a7ae098d22/Standard_Stream/ipcTempFile.log fal se Error occurred fetching the seelog config file path: open /etc/amazon/ssm/seelog.xml: no such file or directory Initializing new seelog logger New Seelog Logger Creation Complete [?1034hsh-4.2$ [Ksh-4.2$ sh-4.2$ sh-4.2$ sh-4.2$ sh-4.2$sudoの禁止するには?
/etc/sudoers.d/ssm-agent-usersでssm-userに許可を削除すればSudoできる権限を剥奪可能です。
sh-4.2$ sudo cat /etc/sudoers.d/ssm-agent-users # User rules for ssm-user ssm-user ALL=(ALL) NOPASSWD:ALLお約束
投稿内容は私個人の意見であり、所属企業・部門見解を代表するものではありません。
- 投稿日:2019-02-28T11:22:31+09:00
JAWS DAYS 2019に行ってきた件(AI/ML系を中心に)
JAWS DAYS 2019に行ってきたので、備忘録です。
総評:とにかく盛り上がってた
1900人超来て史上最高の人数だったそう。
あんま写真撮ってないんですが、確かにどのセッションも黒山の人だかり。
お弁当もランチカーも長蛇の列でした。
運営のみなさんお疲れ様です。スポンサーもいっぱい。
うーん、AWSとも仲良くしてるはずの実行委員長所属会社がスポンサーになってないのはなぜだ。
発表の傾向と回ったところ
当日のタイムテーブルはこちら。
https://jawsdays2019.jaws-ug.jp/timetable/資料のまとめはこちら。
https://qiita.com/hayao_k/items/91c19480948f26b71705実に11トラック。更に展示/同人誌ブースもあり、非常に盛りだくさん、満漢全席の名前の通りという感じでした。
満漢すぎて食いきれないので、2日に分けてほしいとも思ったくらいですが、まあ2日に分けると大変だろうしなぁ・・・Serverless、コンテナ、ハイブリッドクラウドといった基盤周りの新しい軸に関するセッションが結構多かった印象。
IoTとかもちらほらありましたね。SORACOMのハンズオンとか楽しそうだった。
私はAI/ML系のセッションを中心に聞いてきました。
以下、気になったセッションをいくつか紹介。気になったセッション
この3セッションが連続したあたりが、個人的なハイライトでした。
ここに書いてないことも色々と話されていたのですが、気になったところを中心に。[AI/ML 前半] PythonとSageMakerで始める MLチームのみで完結するAPIの構築事例 GVA TECH 武田さん
- ML機能の開発フローは、「分析検証→アルゴリズム開発→学習・モデル変換→APIのデプロイ→プロダクトに反映」
- プロダクトに反映まで行って初めてユーザ価値が生まれる。なので、そのスピードをなるべく高速化したい。
- APIとしてデプロイしてプロダクトに反映するところはインフラまわりのスキルが必要。
- 機械学習の専門家集団であるMLチームは基本的にインフラ周りのスキルはそんなに高くない。彼らにそこをやらせるのはスキルの無駄遣い。
- 一方、インフラ周りの担当を別途用意すると、MLチームとは文化が違ってわかりあうのが難しい。(MLチームのコードがわんぱくすぎる、とか)
- コミュニケーションコストが高くなって、結局速くならない。
- そこで、SageMakerを活用して、MLチームのみで商用環境へのデプロイ可能な状況を作った。
- 結果、新バージョンのAPIリリースがほぼ1日で対応可能に!
[AI/ML] 機械学習における AWS を用いたマイクロサービスアーキテクチャ ABEJA 中川さん
https://www.slideshare.net/yutanakagawa2/aiml-aws
- AI/ML業界は技術の進化スピードがえげつない。
- だから、ビジネスとしては速攻で最新のモデルを取り入れていきたい。
- ところが分析系機能のアーキテクチャが完全にモノリスで、1年位モデルいれかえてない・・・とかいう状況に。
- そこで、モデル部分をマイクロサービスにして、影響範囲を極小化しながら必要なモデルを簡単に差し替えられるようにした。
- ついでに、モデルのフローも組み換え可能に。
- これによって、最新の技術を論文で知り、検証用コードを活用して新たなモデルを作り、すぐにプロダクトに組み込みが可能に。
[BigData] AI/MLシステムにおけるビッグデータとの付き合い方 DeNA 鈴木さん
- AI/ML系の開発をスムーズ・迅速に行うために、3つのロールを設けている。
- AI研究開発エンジニア - 各分野の専門性を持ってる人。研究のウォッチと活用。
- データサイエンティスト - Kagglerの人たち。泥臭い系。
- MLエンジニア - AI技術をサービス上に実装して安定運用を実現するのがミッション。←鈴木さんはここ。
- MLエンジニアはモデル開発以外の部分は何でもやる。AI研究開発エンジニアやデータサイエンティストは基盤周り弱いので。
- 機械的なレベルのデータクレンジングとかも全部やってる
- セキュリティ周りも、普通にやってれば問題が発生しないように整備しておく
- 野良インスタンスが立たないようにとか、GPUインスタンスのスポットインスタンスを使うとか、そのへんもお手伝い。
- SageMakerはスポットインスタンス使えなくて高いのもあるし、意外とニーズがなかった。
所感
というわけで、如何に専門性の高い人のスキルを無駄遣いせずに、彼らのアイデアを最短距離でビジネスに落とし込んでいくかというところが一つのキーポイントなのだな、という感じですね。
でも、そこに向けての工夫ややり方、体制は三者三様。専門家がデプロイまで簡単にできるようにしてあげるのか、そこは他の人が見てあげるのか。デプロイの高速化のやり方もそれぞれ。この辺は組織やメンバーにあったやり方をそれぞれ模索するべきなのでしょう。
他にも色々セッションは聞いたんですが、この3つが一番印象に残ったので取り上げてみました。あといちばん笑ったのは営業セッションだったけどそれはまたどこかで。
- 投稿日:2019-02-28T08:41:46+09:00
AWS LambdaのPHP関数のログ出力について
はじめに
前回の AWS Lambda のCustom RuntimeでPHP用のLayer作成 で作成したLayerを使用します。
(Stackery社のlayerでも問題ないです。)作業環境
LayerのZip作成にdockerを、AWSへのアップロードにaws-cliを使います。
- pyenv
- 1.2.9-2
- pip
- 9.0.3(python3.6.5)
- aws-cli
- 1.16.96(python3.6.5)
- sam
- 0.14.2
作業はMacOSです。
各種インストールは割愛します。使用ソースコード
https://github.com/Sunochi/LambdaTestFuntion
ログ出力について
AWS LambdaでPHPを使用した際の挙動として、ログ出力が不便という点があります。
API Gatewayを使用する場合はブラウザ上にvar_dump()
で表示すれば良いですが、データとして残すためにもCloudwatch logsへ出来る限り可視性が高い状態で出力しておくことが望まれます。
最近はcloudwatch logsの機能で、json形式のログから検索も可能になっているようなので、ログ出力はちゃんとしようと思う毎日です。
さて、今回はprintf
とvar_dump
とerror_log
の挙動の違い、現時点でのPHPでのログ出力方法のベストプラクティスをまとめておきます。テストコード
index.php<?php function print_log(){ $temp_array = [ 'hoge' => "foo", 'var' => 2, ]; printf("Hello World!\nhogehoge"); printf($temp_array); } function var_dump_log(){ $temp_array = [ 'hoge' => "foo", 'var' => 2, ]; var_dump("Hello World!\nhogehoge"); var_dump($temp_array); } function error_log_log(){ $temp_array = [ 'hoge' => "foo", 'var' => 2, ]; error_log("Hello World!\nhogehoge"); $json_temp_array = json_encode($temp_array); error_log($json_temp_array); } function main(){ print_log(); var_dump_log(); error_log_log(); }結果
error_log()
とjson_encode
の組み合わせが最適です。printf
Lambda上のログ詳細: "Hello World!\nhogehogeArray" CloudWatch logs: Hello World! <行切り替え>hogehogeArrayprintfで表示は可能ですが、複数のログを出力した際に、
1行にまとめて表示される問題があります。
\n
がCloudwatch logsでの行切り替えになっているため、想定通りの出力にならないことがありそうです。var_dump
Lambda上のログ詳細: "string(21) \"Hello World!\nhogehoge\"\narray(2) {\n [\"hoge\"]=>\n string(3) \"foo\"\n [\"var\"]=>\n int(2)\n}\n" CloudWatch logs: string(21) "Hello World! <行切り替え>hogehoge" <行切り替え>array(2) { <行切り替え>["hoge"]=> <行切り替え>string(3) "foo" <行切り替え>["var"]=> <行切り替え>int(2) <行切り替え>}実際に出力してみるとわかりますが、とてもログを参考にできたものはないです。ブラウザ上に表示する場合はvar_dump()がいいと思いますが、ログ出力には向いていないのがわかると思います。
error_log
error_logにArrayを入れるとwarningが出るため、先にjson_encodeしておきます。()
```
Lambda上のログ詳細: ""CloudWatch logs: Hello World!
<行切り替え>hogehoge
<行切り替え>
{
"hoge": "foo",
"var": 2
}
```printf, var_dumpと比べて、行切り替えのタイミングが大分よくなりました。
ただ、\nは行切り替えしたくないので、以下のラッパー関数を作成します。logging.phpfunction logging ($output) { $log = ""; if(is_array($output)){ $log = json_encode($output); $log = str_replace("\n", "\\n", $log); } else { $log = str_replace("\n", "\r", $log); } error_log($log); }結果
Lambda上のログ詳細: "" CloudWatch logs: Hello World! hogehoge <行切り替え> { "hoge": "foo", "var": 2 }いいですね!Lambda上のログ詳細に出したい場合(デバッグ時)は、
var_dumpを使用すればいいと思います。まとめ
PHPのログ出力について、ログ関数を入れてまで本格的にやりたくないので、手軽にできる方法を探しました。
今のところ、error_logのラッパー関数が使い心地がいいですが、よりオススメの方法があれば知りたいです。参考
- 投稿日:2019-02-28T01:11:34+09:00
【メモ】ローカルからAWSのEC2にフォルダを転送する際に詰まったところ
背景
AWSのEC2にファイル転送するときに少し詰まったのでメモ
フォルダ転送コマンド
キーのあるディレクトリに移動し以下のコマンドを実行すればローカルフォルダを転送できる
$ scp -i [.pemファイルの場所].pem -r [転送元のローカルフォルダの場所] [ユーザー名]@[パブリックDNSかパブリックIP]:[転送先の場所]・オプションの意味
-i :接続に使用する公開鍵ファイルを指定する
-r :ディレクトリ内を再帰的にコピーするエラー
以下のようなエラーが出た
Permission denied (publickey).解決策
AWSで作成したインスタンスのオーナーは”ec2-user”(Amazon Linux の場合)しかし、デフォルトではアクセス権限がないため、”ec2-user”(オーナー)に書き込み権限を与えることで解決した
awsインスタンスにssh接続して以下のコマンドを実行し書き込み権限を与える
sudo chown -R ec2-user [転送先]参考文献