TILやってるのでリポジトリのリンク貼っとく

github.com

"Today I Learned" ですね。今日学んだこと。

ブログに書こうと思うと綺麗に書こうとか心理的ハードルが上がりがちなんだけど、そのせいで外向けアウトプットがゼロになってしまうのは嫌だなー、というところで始めた。

適当に書いたものも積極的にあげていく方針、なんだけど、なんだかんだコミットしてないメモ書きもローカルには結構ある。

内容はもう完全にチラ裏で、後で自分が振り返ったときにかろうじて内容がわかるかも、っていうレベル。

それでも自分が積み上げたものが可視化されるっていうのはやっぱり良くて、ほんの少しだけモチベーションが上がったり。

大したことは書いてなくて役に立つようなものでもないんですが、やってるぞ、っていうことで貼っておきますね。

最低限の設定でAmazon ECS(+EC2)なNginxを立ち上げる

aws.amazon.com

いまECSを使うならEC2インスタンスをホストとせずFargateを使うのが基本になりそう。
ここではFargateではなくEC2インスタンスを使う方法で進めます。

ちなみにECSは「Elastic Container Service」の略ですが、ひと昔前は「EC2 Container Service」でした。

大まかな流れ

  1. 新しいタスク定義の作成
  2. クラスターの作成
  3. サービスを作成してクラスターで実行・維持するタスク定義を指定

タスク定義

マネジメントコンソールでAmazon ECSの画面を開いたら左メニューから「タスク定義」を選択し「新しいタスク定義の作成」をします。
「起動タイプの互換性の選択」をする画面が表示されますが、ここではEC2を選択。

次は「タスクとコンテナの定義の設定」。 「タスク定義名」を適当に(nginx-taskとか)入力しましょう。

あと、少し下にスクロールして「コンテナの定義」から「コンテナの追加」をします。
「コンテナ名」はお好きにnginx-containerみたいに入力して。
「イメージ」は nginx:alpine とかするとDocker Hubからイメージをとってくるようになってます。

タグはドキュメントを参照してください。
https://hub.docker.com/_/nginx

「メモリ制限」は推奨されている最低値の300。
「ポートマッピング」はホスト、コンテナともに80としておきます。

これ以外の設定値は特に触らず、「作成」します。

クラスター作成

タスク定義できたらクラスターの作成です。

左メニューから「クラスター」を選んで「クラスターの作成」と進み、最初の「クラスターテンプレートの選択」は EC2 Linux + ネットワーキング を選びます。
「クラスター名」はなんでもいいです。nginx-clusterにしときます。
「EC2インスタンスタイプ」はお試し目的なのでt2.microとか小さいのにしとくといいでしょう。

最低限の設定はこれくらいです。
「作成」しましょう。

サービス作成

最後ですね。サービスの作成です。

クラスターの作成が終わると「クラスターの表示」というボタンが出てくるのでそれを押すか、クラスターの一覧から作成したクラスター選択します。
「サービス」というタブがあるので、そこから「作成」しましょう。

「起動タイプ」はEC2。
「タスク定義」と「クラスター」は先ほど作成したものが選択されていることを確認してください。
「サービス名」は例によってnginx-serviceとして、「タスクの数」は1としときます。

あとは触らずに「次のステップ」を押し続けます。
最後の確認画面で「サービスの作成」です。

動作確認

EC2インスタンスが作成されているので、そのパブリックIPを参照するか、クラスターの「タスク」タブを開いてタスクのリンクを押すと、下にコンテナが表示されており、そこに外部リンクが記載されています。

ブラウザからアクセスするとNginxのウェルカムページが表示されるはずです。やったね。

Serverless Frameworkを使ってTypeScriptなAWS Lambdaをセットアップ

マネジメントコンソール上でコードを書いていくのは辛い。
zipに固めてaws-cliでアップロードっていう方法もあるけれども、今回はServerless Frameworkを使います。

serverless.com

github.com

$ npm --version
6.10.3
$ npm install -g serverless
...
...
$ sls --help

Commands
* You can run commands with "serverless" or the shortcut "sls"
* Pass "--verbose" to this command to get in-depth plugin info
* Pass "--no-color" to disable CLI colors
* Pass "--help" after any <command> for contextual help
...

資格情報(credentials)を設定。もちろん事前にユーザーは作っておく。

$ sls config credentials --provider aws --key xxxxx --secret xxxxx
Serverless: Setting up AWS...
Serverless: Failed! ~/.aws/credentials already has a "default" profile. Use the overwrite flag ("-o" or "--overwrite") to force the update

おっと。設定済みだった。

$ cat ~/.aws/credentials
[default]
aws_access_key_id = dummy
aws_secret_access_key = dummy
...

さっきのコマンドに --profile オプションを追加して、デフォルトではなく別のプロファイルとして設定する。

$ sls config credentials --provider aws --key xxxxx --secret xxxxx --profile xxxxx

設定に成功したら ~/.aws/credentials に追加されてる。

Hello World

$ sls create --template aws-nodejs-typescript --path helloLambda
Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "/path/to/helloLambda"
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v1.52.0
 -------'

Serverless: Successfully generated boilerplate for template: "aws-nodejs-typescript"

$ cd helloLambda
$ sls deploy

  Serverless Error ---------------------------------------

  Serverless plugin "serverless-webpack" not found. Make sure it's installed and listed in the "plugins" section of your serverless config file.
...

なん、、だと、、

$ ls
handler.ts        package.json      serverless.yml    tsconfig.json     webpack.config.js

node_modules がない。

$ npm install
$ ls
handler.ts        node_modules      package-lock.json package.json      serverless.yml    tsconfig.json     webpack.config.js
$ sls deploy
...
  Serverless Error ---------------------------------------

  The security token included in the request is invalid.
...

おっと。多分デフォルトのプロファイルが使われてるな。。
どのプロファイルの資格情報を使うか、指定してあげないとだった。

$ vim serverless.yml
...
provider:
  name: aws
  runtime: nodejs10.x
  # profileにプロファイル名を指定
  profile: profile-name
...
$ sls deploy
...
  Serverless Error ---------------------------------------

  User: arn:aws:iam::xxxxx is not authorized to perform: cloudformation:CreateStack on resource: arn:aws:cloudformation:xxxxx
...

今度は権限がない、と。マネジメントコンソールから権限追加。

$ sls deploy
...
Serverless: Stack update finished...
Service Information
service: hellolambda
stage: dev
region: us-east-1
stack: hellolambda-dev
resources: 10
...

できたけどリージョンが us-east-1 になってますな。

$ vim serverless.yml
...
provider:
  name: aws
  runtime: nodejs10.x
  profile: profile-name
  # リージョン指定追加
  region: ap-northeast-1
...

もう一度 sls deploy
コンソールから無事東京リージョンにLambda関数を作成できていること確認。
別のリージョンに作ってしまった関数は削除。

作成時に出力されたエンドポイントに対してcurlを叩いてみる。

$ curl -X GET https://xxxxxxx.ap-northeast-1.amazonaws.com/xxxxx
{
  "message": "Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!",
  ...

ちゃんと動作している。

sls invoke でもええよ。

$ sls invoke -f hello
{
    "statusCode": 200,
    "body": "{\n  \"message\": \"Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!\",\n  \"input\": {}\n}"
}