d.sunnyone.org
sunnyone.org

ページ

ラベル AWS の投稿を表示しています。 すべての投稿を表示
ラベル AWS の投稿を表示しています。 すべての投稿を表示

2020-06-16

AWS Lambda + TypeScript の構成メモ

AWS Lambda の関数を Node.js + TypeScriptで書くとき、どのような構成にすると便利かまとめたメモ。デプロイにはAWS SAMを使うことを想定。

ディレクトリ構造

src/ts/functions/(スタック名)/(関数名).ts をwebpackのエントリポイントとして、以下のようなディレクトリ構造にする。
src/
  templates/        # CloudFormationテンプレート
  ts/
    functions/
      (スタック名)/
        (関数名).ts # エントリポイント
    cli/
      (関数).ts     # コマンドラインでの動作確認
    lib/            # 共通コード群(AWS Lambdaのランタイムに依存しない部分)
      foo/
        bar.ts
スタック名があるのは、デプロイパッケージ(zip)をスタック単位にすることを想定。デプロイツールの都合でここは調整したほうがいいかも。

コマンドラインで動作確認できるようにする

AWSのリソースを操作する系のLambda関数を実装する場合、その処理をコマンドラインで実行できるようにしておくと便利。 cli/にコードを配置し、ts-nodeを使ってpackage.jsonの"scripts"で呼び出せるようにしておく。
  "scripts": {
    "cli:my-operation": "ts-node src/ts/cli/my-operation.ts",
  }
コードとしては、yargsでコマンドライン引数を解析して、関数に渡すだけのイメージ。
$ yarn cli:my-operation -a my-arg

webpack設定

node_modulesを持っていけば動くのだが、productionのみにしたりと面倒なので、webpackする。 例としては、こんな感じ。 ポイントは、externals: ["aws-sdk"]。標準のものやLambda Layerで提供しているものはここで除外する。ネイティブモジュールは、Lambda Layerで提供すると良いと思う。minimize: falseはコンソールで読む用。どっちでもいい。

tsconfig.json

Node v12のときはtarget: es2019。moduleはcommonjs。

source-map-supportを入れる

webpackするとスタックトレースが不便になるので、source-map-supportを入れる。
yarn add -D source-map-support @types/source-map-support
して、各エントリポイントファイルの先頭で
import "source-map-support/register";
する感じで。

必要に応じてnpm moduleにしてシェア

CloudFormation templateと、ビルドしたjsをnpm moduleにしてnpm registryにpublishしておくと、同一構成を作りやすくて便利。

2018-03-26

AWS CloudFront Lambda@Edge の罠たち

CloudFront Lambda@Edge は、Lambda関数を実行しCloudFrontのリクエスト/レスポンスに手を加えることができるサービス。CloudFront⇔オリジン間、ビューワ⇔CloudFront間のリクエスト側/レスポンス側の4つの場所から適用する場所を選ぶことができる。

適切に使えば便利だと思うが、使ってみないとわからない罠が多いので、経験した範囲をまとめておく。

CloudFrontにはバージョンつきのLambda関数のARNを設定する必要がある

CloudFront BehaviorにLambda関数のARNを設定するのだが、名前だけのARNは設定することができず、バージョン番号入りのものを設定する必要がある。

つまり、Lambda関数の中身を書き換えたら、新しいバージョン番号を発行して、その番号をCloudFrontに設定する必要がある。

毎回手動でなんて現実的ではないので、AWS Serverless Application Model (AWS SAM)を利用してCloudFormationでLambda関数をデプロイし、AutoPublishAlias 機能によってバージョン番号を自動的に設定するのが現実的であろう。同一スタックであれば、CacheBehaviorsに以下のように設定する。
LambdaFunctionAssociations:
  - EventType: origin-response
    LambdaFunctionARN: !Ref "Function.Version"
これが何を意味するかというとLambda関数を更新する度にCloudFront Distributionを更新する、すなわちコードを書き換えるたびに数十分かかるということを意味する。

Lambda@Edgeに設定する関数はus-east-1リージョンに配置する必要がある

Lambdaはap-northeast-1でも利用可能だが、Lambda@Edgeに設定する関数はus-east-1に配置する必要がある。先のCloudFormationスタックを作るのであれば、us-east-1リージョンで作る必要があるということになる。

日本のサービスであればap-northeast-1に配置することも多いと思うが、スタック間でのパラメータの引継ぎに利用できるクロススタック参照は同一リージョンでしか利用できない。したがって、us-east-1→ap-northeast-1のスタック間でリソースの参照がある場合、自前でパラメータ引き渡しをするための仕組みが必要となる。

Lambda@Edgeで設定した関数は各リージョンにレプリカが作られて実行される

us-east-1にLambda関数を設定したからといって、us-east-1で常に実行されるかというとそうではなく、CloudFrontのエッジのリージョンに必要なタイミングでコピーされて実行される。

「オレがCloudFront エッジをサービスしたいのは日本だけ!」ということはできないので、日本を含もうとすると、多くのリージョンにレプリカが作られることになる。

レプリカはLambdaから見ると、us-east-1.というprefixがついた変更不可能な関数にしか見えない。これは、Lambda@Edgeに設定した関数のログは各リージョンのCloudWatch Logsに散らばって配置されるということを意味する。 もしログを集約したりフィルタしたりといったことをしようとすると、ほぼ全リージョンのCloudWatch Logsのリソースに対して手続きを行う必要がある。

Lambda@Edgeでは環境変数は利用できない

Lambdaで環境ごとの値を設定するのに便利な環境変数は、Lambda@Edgeでは利用できない。よって、コードに埋め込むか何らかのAPI問い合わせで値を取得する必要がある。今回 必要な値は別のリソースのARNだったので、レプリカ元(マスター)のLambda関数リソースのタグに設定し、以下の手順で取得した。
  1. context.invokedFunctionArnからレプリカ関数のARNを取得
  2. レプリカ関数のARNからリージョンを取得し、そのリージョンに対してレプリカ関数を問い合わせるlambda:GetFunctionの呼び出しを行いマスター関数のARNを取得
  3. マスター関数のARNからリージョン(us-east-1)を取得し、lambda:GetFunctionを呼び出してタグを取得
別の関数の環境変数だとか、DynamoDBだとか、状況により選択肢はあると思うが、いずれにせよ工夫が必要である。

Lambdaよりもタイムアウトなどの制限が厳しい

通常のLambda関数よりも、制限が厳しくなっている(Lambda@Edge の制限)。

例えば、Lambda単体であればタイムアウトは300秒まで設定できるが、オリジンリクエスト/レスポンスに対する関数だと30秒、ビューワーだと5秒など項目によっては厳しくなっているので注意が必要。アップロードサイズも注意。

以上のように使えそうに見えて使ってみるとどうしよう、みたいなところが多いので皆様お気をつけください。

2015-11-03

図解 Amazon EC2 Container Service (ECS)

本当にざっと使ってみたので、説明用に絵にしてみた、という話。説明書きはつけたけど、図解と言うほどには、説明していないかも。



触った感じ、動き的にはこうじゃないかと思うのだけど、違っているところがあるかもしれない(のでRev0.1)。

並べるものではないのだけど、Beanstalkを使ったときは、Beanstalkが広く面倒を見るせいで、便利そうな反面意識するところが増えてかえってしんどいなと思ったのだけど、ECSは層の分割がしっかりしているおかげで、だいぶ扱いやすそうだなと思う。「Agent入りのインスタンスくれたら、そこのDockerコンテナを管理するよ。そこで何動かすかは知らないよ」という感じで、役割分担がはっきりしている。

Agent入れればdistributionはなんでもOKということだけど、こだわりがなければECS-Optimized Amazon Linuxを使っておいて、なるべくホスト側には手を入れないというのが、らしい使い方だろうか。

ECS-Optimized Amazon Linuxがあるとはいえ、VMが利用者管理なのはAWSらしいなと思う。もうちょっと基礎側がmanagedなやつがあればいいなぁと思うけど、そういった向きはAPI Gateway + Lambdaとかになるのかねえ。

2015-02-07

Amazon Glacier の取り出し料金計算機を作った

S3よりもデータ保管の料金が安いAWSのサービスAmazon Glacier。しかし、取り出しの料金が難解で、時折話題になるので、もうちょっと視覚的にわかるようにできないかなと思ってちょっとしたツールを作ってみた。→http://glcalc.sunnyone.org/


基本的には、全体サイズと取り出す容量をスライダーでさらっと調整してもらえれば、グラフが変化するのでホバーして読めばOK。

FAQの数値と合ってはいたので、たぶん合っているとは思っているが、注意書きにもある通りざざっと動かして目星をつけて、そのサイズで実際に計算してみるのが良いかと思う。無料枠の計算も入っているので、無料でいけるのはどんなもんかというのを見るのが主になるかな。ここで計算していない料金達も馬鹿にならないはずなので、それも別途計算が必要。

--

実はNVD3をちょっと使ってみたかった。スライダーが欲しかったのでPureでなくFoundationを使ったら、意図せずResponsiveになった。あとはデータバインディングでVue.jsを使ってるのはまぁいつもの感じ。