Lambda+S3+EC2を使用してできるだけ安くリアルタイムwebPエンコードをやってみる

S3にアップロードされる jpg画像をリアルタイムで webP にエンコードしたかったので 色々やってみた。   要件 S3 バケットには毎月1000万枚の2.2MB程度の jpg画像がアップロードされると仮定 これをアプリが引っ張る前にできるだけで速く webP にエンコードする必要性があります。 webP にエンコードする理由としては、画像の容量が小さくなることでユーザーのストレスを無くす、S3 にかかる料金を安くする、CloudFront の料金を安くするため。 ちなみに何でアプリでやらないかというと、iPhone で撮った生の画像を iPhone でエンコードを行うと、アプリがフリーズするぐらい結構重い処理だからです。致し方なし。   ① Lambda だけで全てやってみる S3 にアップロードをトリガーとして Lambda を起動して、Lambda でエンコードから S3 にアップロード、既存の jpg画像を削除を行うと、最小スペックで 22秒という脅威的な数値を叩き出します。 ちなみにメモリの使用量は 108/107MB 程度です。重いなあ… 全ての Lambda スペックで試し、一番安いスペックは 256MB でした。 これでも 11秒です。 256MB 枚数 秒数 課金 1枚辺り実行時間 無料枠 1秒辺り課金額 10000000 110000000 452.028 11 1600000 0.00000417 20000000 220000000 910.728 ちなみにひと月で 10000万枚を捌き切るにはこの Lambda 関数は並列で 42 個、必要になります。 $452 * 42 = 約210万… センキューAWS! これに CloudFront の料金も加算したらとんでもない額ですね。   ② エンコード用のサーバーを用意してみる not EC2 Lambda 関数を2つ用意し、Lambda – webP request(128MB) は Convert Server にある変換用サーバーにリクエストを送り、Convert Server がステータスコード 200 以外を返したときは、Lambda – webP encoder を呼ぶ係、Lambda – webP encoder は Convert Server  に代わってエンコードしてくれます。 Convert Server は Lambda の料金を節約するために、リクエストを受け取った瞬間に 200 を返すようにしています。サーバーにリクエストがくれば途中で天変地異や、タイミングよくサーバーが壊れる、リソース不足以外で、きちんと動作するようなコードであれば対策はできるであろうと思います。 この構成にしたところ、通常時(Lambda – webP encoderが呼ばれない)であれば、課金対象実行時間が 1,500ms となるので、Lambda だけだと { (1.5 * 10000000)…

no image

保護中: 田胡研で楽をする方法

この投稿はパスワードで保護されているため抜粋文はありません。

S3をCloudFrontから配信&LambdaとWAFを組み合わせて利便性とセキュリティを確保してみる

この記事は、AWS Lambda Advent Calendar 2017 の5日目となります。 今回は S3 にある画像ファイルを CloudFront から配信をしつつ、 CloudFront のアクセスログを Lambda で解析を行って、WAF の IPリストへ追加を行って、セキュリティの担保を行ってみようと思います。   S3 を CloudFront から配信する理由 前提条件に、弊社の S3 バケットにはユーザー個人が撮影した画像がアップロードされます。 なのでセキュリティには気を置いてしっかり運用していく必要性があります。 AWS SDK を使用すれば S3 から署名付きURLが吐き出され、これにアクセスすれば画像を取得できます。が、この署名付きURLには有効期限が設定されており、アプリから使うにはちょっと面倒です。 S3 を CloudFront から配信をすると、WAF が使えるようになるので固定URLで配信しつつ、セキュリティも担保できます。   構成 ①ユーザーが CloudFront にアクセスを行う ②リクエストヘッダー等を WAF へ送る ③WAF にあるルールと照合し、結果を返す ④③がOKなら S3 から画像を持ってくる(NG なら 403 を返す) ⑤アクセスログを S3 へ保存する ⑥⑤のタイミングで、Lambda が発火する ⑦アクセスログに HTTPステータスコードが 200 以外のものがあったら、IPを WAF の IPリストに追加する Lambda 関連のアドベントカレンダーなのに、Lambda の部分を特筆するところがねぇ…   CloudFront ディストリビューションの作成 オリジンに、対象の S3 バケットを。 ログの設定も何となく分かると思います。 S3 は CloudFront からのみアクセスできるようにしておきます。 ブルートフォースアタック等で、キー(/user_id/hoge_id/file_name_.jpg みたいな)がバレないように、こうします。CloudFront + WAF を組み合わせればキーがバレる前にブラックリストに入れて、アクセスを拒否できます。   WAF web ACL の作成 AWS resource to associate には先程作成した CloudFront のディストリビューションを設定します。 ルールの作成部分では IP address で作成する。 文字列判定を使えば特定の文字列をヘッダーに載せるとアクセスできるなんて仕組みもできます。   こんな感じです。 最初に IPアドレス判定を行ってから、文字列判定のルールでヘッダー認証をします。順番が大事です。今回はなんちゃってヘッダー認証があるので、デフォルトアクションは全て 403 を返すようにしています。   Lambda スクリプトを作る 言語は好きなものを選んでください。 今回僕が書いて運用しているコードを貼っておきます。 IP_SET_ID には WAF -> IP addresses の自分で作成した空のルールにアクセスすると、URLにある /ipsets/<ここ> を指定します。…

CentOS7/UbuntuからWindows10のPCをリモートシャットダウンしてみる

Windows側 管理者権限+パスワード設定がしているアカウントを作成する(既にある場合はスキップ) TCP:445, 139 を開ける Linux側 コマンドを入れる Debian系:apt install samba-common RHEL系:yum install samba 実行する net rpc shutdown -I ipaddress -U "username%password" -f -t 0 -C "Shutdown"

RDS for MySQL でSELECT結果をCSVに吐き出す

機会があって調べていると一筋縄ではいかなかったので覚書。 2ヶ月ぶりの記事ですが普通に生きています。   INTO OUTFILE は使えない RDS for MySQL(Aurora) v5.6.10 では INTO OUTFILEを実行するとエラーで使えない ERROR 1045 (28000): Access denied for user 'xxxx'@'%' (using password: YES)   StackOverFlow の人気コマンドを実行するとレイアウトが崩れる [crayon-5b270dd26f23f669340043/] これで吐き出される CSV は見るに堪えないものができてしまう。 MySQLのバージョンだったりが関係あるのかもしれない。   mysqldump-to-csv を使う https://github.com/jamesmishra/mysqldump-to-csv [crayon-5b270dd26f24d237187556/] これを使うと何故かヘッダが付与されないけど そこは手動で。

EdgerRouter v1.9.7にするとTCP Dup ACKが発生して、ネットワークが不安定になる

Edge Router ER-8 を使っているのですが 最新のファームウェア v1.9.7(hotfix-2)を使うと外部からアクセスするのに 40秒近くかかるようになったので共有として。 EdgeRouter ER-8を買ってセットアップしてみた   症状 EdgeRouter v1.9.7, v1.9.7-hotfix1, v1.9.7-hotfix2 いずれのファームウェアにアップデートをすると ネットワークが不安定になるようになった。 TTFBが35秒程かかり、ロードが終わるのに40秒かかる現象になってしまった。 ※TTFB – Time to First Byte クライアントがHTTPリクエストを送信してからサーバーが返してクライアントが最初の1byteを取得するまでの時間 EdgeRouter <-> ロードバランサー <-> Webサーバー 上記構成で、ロードバランサーでパケットキャプチャをしてみた。   TCP Dup ACK が発生したのち、TCP Retransmission が頻発してます。   TCP Dup ACK とは パケットロス等で、受信者が想定しているシーケンス番号より、大きな値のシーケンス番号が送信者から送られてくることがあります。 すると、受信者は自分が想定しているシーケンス番号をACK番号にセットしたACKを直ちに送信者に送ります。これがDupACKです。 http://troushoo.blog.fc2.com/blog-entry-111.html 今回の場合はサーバーが効率目的で一方的にパケットいくつかを送った結果、パケットロス等が原因で届かなかったためか、クライアントはACK=1を期待してパケットを投げます。 しかし投げたパケットも届かなかったためか、もう1度ACK=1を期待してパケットを投げる。 これが重複したACK = DUP(licate) Ack(nowledgement)です。   TCP Retransmission とは Seq#が進んでおらず、TCP Fast Retransmission, TCP Out-Of-Order, TCP Spurious Retransmission の いずれにも該当しないパケット http://milestone-of-se.nesuke.com/knowhow/wireshark-tcp-error/ 今回の場合は、TCP Dup ACKを受け取ったサーバーが 再送のためTCP Retransmissionなパケットをクライアントに送ります。 しかし再送しまくってる(Seq=1)のにも関わらず、クライアントから返送がないため 9回も同じパケットをサーバーからクライアントに送信してます。(最後の9回目だけサイズが小さい) No.144 で初めてクライアントから サーバーが送った Seq=1 + LEN=1452 を受け取ったよパケットが届きました。 その他のTCP Retransmissionなパケットも、No.147, 149で届いてることが確認できました。     EdgeRouter v1.9.1.1 では ああ…綺麗だ。 直接的には原因は分からない(v1.9.1.1 と v1.9.7の差分が多すぎて辛い)。 時間があるときに見ていきたいと思います。 もし記事にミス等がありましたらコメントしてくださると助かります。

Systemdで動かすNode.jsでnewrelic agentを使う

また Systemd の話です。 Node.jsのプログラムをsystemdで動かすと意図しない動作をどうにかする GolangのGinをSystemdで動かすのにハマった 今回はバックエンドに newrelic を導入しようとしたところ、 うまく動作しなかったため解決策を載せておきます。   原因 Systemd のせいです。 newrelic のモジュールはアプリケーションフォルダに、ログファイルを吐き出すんですが モジュールがこれを見つけることができない(cgroupsのせいで /newrelic-log.txt を見る)ため   解決 newrelicのサイトに行くとnewrelic.jsを配置しないといけないわけですが [crayon-5b270dd26f2f6869324039/] こんな感じになってると思います。 モジュールを見ていくと分かったんですけど これ以外にも設定できる項目がたくさんあります。 今回はログをきちんと見つけられるように絶対パスで指定します。 [crayon-5b270dd26f2fc353449891/]  

AnsibleでコピーするときはSynchronizeモジュール使ったほうが幸せになれる

背景 Ansibleでターゲットホストに何かをコピーするとき copyモジュールを使ってる人はとても多いと思います。 しかし恐ろしいぐらい遅いため、ansible copy slow何かで調べると 色々対策が書かれている記事があると思います。 まあそれを試しても劇的な改善はなく、結果として意味のないものです。   Synchronizeモジュールを使う Ansible – synchronize Copyモジュールと同等のことをやってみます。 1. ターゲットホストにファイルを配置する [crayon-5b270dd26f3ce869607744/]   2. パーミッションを変更する [crayon-5b270dd26f3d7032485157/] Synchronizeモジュールにもownerやgroupオプションはあるんですが これは Ansible 実行マシンに存在するユーザー、グループで且つ、 ターゲットホストにも存在しないといけないという制約があるので、 別タスクでパーミッション等を変更する必要があります。   比較 全部で350行ぐらいある Playbook の中のcopyモジュール版と Synchronizeモジュール版で比べた結果です。 Copy real 4m25.575s Synchronize real 2m12.755s 圧倒的