- 投稿日:2022-01-27T23:48:26+09:00
AWS SESを使いたてでメールが届かない時に確認したいこと
サンドボックスが原因かもしれません。 “サンドボックス” is 何 サンドボックスは、通常、システム障害やソフトウェアの脆弱性の拡散を軽減するために、実行中のプログラムを分離するためのセキュリティメカニズムです。 ... 高度に制御された環境を提供するという意味で、サンドボックスは仮想化の具体例と見なすことができます。 SESにおいてはどういうことだってばよ? SESにおけるサンドボックスは、メール送受信の不正利用や悪用などを防ぐため、新規に作成されたアカウントに一定の制限が設けらた状態で提供されるSESの利用環境です。 制限内容(2022.1.27現在) Eメールの送信先が検証済みEメールアドレス・ドメイン、メールボックスシミュレーターに限定される 最大で24時間あたり200メッセージ 最大で1秒あたり1メッセージ つまり、「sesに登録されているアドレス・ドメイン宛てにしか送信できないよー。レート制限もあるから定められた時間内で送信量の制限を超えないように使ってねー」ということですね。 そしてダッシュボードにも初期状態だと警告が出ていますね。 上記を踏まえ 「サンドボックス環境でのメール送信利用の設定もしくはサンドボックスの解除はもうやってるよ!」という方 ⇒ すみませんでした。本記事でお力になれることはなさそうです。さよなら。。 「サンドボックス環境設定があったのか、特に設定解除とかメールアドレスの認証とかやってなかったな」という方 ⇒ 読む価値あるかもです。 どういったアプローチでメール利用できるようにするのか ◾️ サンドボックス環境で使えれば良いやーって方 対象:不特定多数のユーザーへのメール送信とかしなくても良い。とりあえずに検証だけSESを利用できればいいんだって人 検証済みのIDとして送信対象のメールアドレスを追加しましょう。 sesコンソールサイドバー > Verified identities > Create identity 追加すると対象のアドレスに確認用メールが送られます。(リンクを踏めば認証完了で、UnverifiedがVerifiedに変わります。) これでメールアドレスの認証ができたので、対象のメールアドレスであればサンドボックス内からでもSESを利用し、メールが送信できるようになります。 ◾️ サンドボックス環境から脱したい方 対象:不特定多数のユーザーへのメール送信が必要なんだ、リリースも近いんだよ、早くテストさせろよって人 残念ながらあなたの力ではどうにもなりません。サポートセンターへサンドボックス解除依頼の申請をしましょう。 SESコンソールサイドバー > Account dashboard > Request production access フォームの解説をします。 Mail type マーケティングかトランザクションか。 マーケティングはメルマガなどのコンテンツ一斉配信での利用、トランザクションは何らかのトリガーによって自動配信されるメールのイメージで良いかと思います。 Website URL SESを利用するサービスのURLです。 Use case description 実際にSESを利用する方法。(多分どういった用途で使うのかを書けばよいと思います。) また、公式ではこの項目について、以下の内容の回答も求められています。 メーリングリストをどのように構築または取得しますか? バウンスや苦情はどのように処理しますか? 受取人はお客様からの E メールの受信をどのようにオプトアウトできますか? このリクエストで指定した送信レートまたは送信クォータは、どのように選択しましたか? Additional contacts *- optional* リクエストに関する通知の宛先メールアドレス。 Preferred contact language サポートセンターからの返信をどの言語で受け取るか。 Acknowledgement 利用規約の同意的なやつですね。 上記の内容を入力し、送信しましょう。24時間以内に一次回答もしくは承認の連絡がくるみたいですね。 承認が降りれば、メールで制限緩和の旨が送られてくるようになります。 制限が緩和されれば基本的に送信先のドメイン等に縛られることなく自由にSESによるメール機能を利用できるようになるかと思います! おわりに ローカルでは別のメール送信ツールを利用し、動作確認はできていたが、デプロイ環境でSESを利用した際に動かない、あれ?とならないためにも仕様は把握しておきたいですね。 サンドボックス解除も早ければ翌日には審査が完了し、制限が緩和されるという話はよく聞きますが、サービスのリリースが近づいた際にバタバタしないためにも余裕を持って申請できるといいですね。
- 投稿日:2022-01-27T23:35:26+09:00
lambdaからECS:RunTaskを使用し、Taskを起動する
業務でLambdaの実行時間に引っかかる処理を切り分けるためにLambda->ECSTask実行を行いました。 ServerlessFlameWorkを使用したNode.js/TypeScript環境でECSのTaskを実行する手順です。 Python3&boto3を使用した記事はこちらです。 環境 Node v14.7.0 "typescript": "^4.1.3" "serverless": "^2.23.0", "serverless-esbuild": "^1.17.1", 結論 ecsTask.ts import { ECSClient, RunTaskCommand, RunTaskCommandInput } from '@aws-sdk/client-ecs'; const client = new ECSClient({ region: 'ap-northeast-1', }); const { TASK_DEFINITION, CLUSTER, SUBNETS, SECURITY_GROUP } = process.env; const runTask = async () => { const input: RunTaskCommandInput = { cluster: CLUSTER, taskDefinition: TASK_DEFINITION, launchType: 'FARGATE', networkConfiguration: { awsvpcConfiguration: { subnets: SUBNETS.split(','), securityGroups: SECURITY_GROUP.split(','), assignPublicIp: 'DISABLED', }, }, overrides: { containerOverrides: [ { name: 'app', command: ['npm', 'start'], }, ], }, count: 1, }; const command = new RunTaskCommand(input); await client.send(command); }; export { runTask }; serverless.yml provider: iamManagedPolicies: - arn:aws:iam::aws:policy/AmazonECS_FullAccess 解説 ハマりポイントはIAMRoleとRunTaskCommandInputでした。 IAMRole 下記でいけるかなと思いましたが、AccessDeniedされました。 serverless.yml provider: iam: role: statements: - Effect: Allow Action: - ecs:RunTask Resource: - '*' 期待しているRoleも含まれてしまうので、FullAccess系は使用したくないのですが、一旦これで行います。 必要なActionが分かり次第、更新します。 RunTaskCommandInput 公式を見ると、TaskDefinitionだけ必須っぽいのですが、他のプロパティも必要です。 最初に記載したプロパティを指定して動きました。 ecsTask側のnetworkmodeが"aws-vpc"でなければ、networkConfigurationは必要ではないかもです。 ecsTask.ts const { TASK_DEFINITION, CLUSTER, SUBNETS, SECURITY_GROUP } = process.env; const input: RunTaskCommandInput = { cluster: CLUSTER, taskDefinition: TASK_DEFINITION, launchType: 'FARGATE', networkConfiguration: { awsvpcConfiguration: { subnets: SUBNETS.split(','), securityGroups: SECURITY_GROUP.split(','), assignPublicIp: 'DISABLED', }, }, overrides: { containerOverrides: [ { name: 'app', command: ['npm', 'start'], }, ], }, count: 1, }; const input = { subnets: SUBNETS.split(','), securityGroups: SECURITY_GROUP.split(','), } 上記は環境変数(string)を配列に変更しています。 自分はServerlessFlameWorkでの環境変数の設定にこちらのclassmethodさんの記事を参考にしています。 あとはoverrides.containerOverridesのnameは必須です。 あとがき ここまで読んでいただきありがとうございます。 疑問点等あれば、質問していただければ答えます! 最近見た映画の主題歌がマカロニえんぴつだったからか、またハマり出しました。 好きな音楽を聞きながらコードを書くのが好きな今日この頃です。 ノリノリでコード書いているので周りはちょっと引いているみたいですが。。笑
- 投稿日:2022-01-27T22:49:06+09:00
FargateでNginxコンテナをデプロイする時、「worker_rlimit_nofile」の値はタスク定義で設定したulimits値以下にしなくてはならい
タイトルのままです。 概要 もうタイトルで伝えてたいことは書ききったのですが、せっかくなので経緯を述べておきます。 AWS FargateでNginxとLaravelコンテナをデプロイしていました。 以前、パフォーマンスチューニングでNginxのconfigファイルの設定について、こちらの記事を参考にゴニョゴニョしていたのですが、それからしばらくたった後、あることに気づきました。以下はfargateにNginxコンテナをデプロイした直後のコンテナログです。 [alert] 29#29: setrlimit(RLIMIT_NOFILE, 180000) failed (1: Operation not permitted) なんとworker_rlimit_nofileの設定が失敗している!? 原因追求したところ、どうやら上で設定している180000という数字がよくなかったようです。 原因 Fargateにコンテナをデプロイするには、「タスク定義」を設定する必要がありますが、このタスク定義で設定していたulimits値を超えていたことが原因でした。 task-definition.json(抜粋) "containerDefinitions": [ { "ulimits": [ { "name": "nofile", "softLimit": 65536, "hardLimit": 65536 } ], } ここでulimits値をソフト/ハード共に65536に設定しているので、worker_rlimit_nofileの値は"65536以下"にする必要があるようです。 nginx.confファイルを再設定後、無事にこのエラーは解消されました。 nginx.conf #worker_rlimit_nofile 180000; コメントアウト worker_rlimit_nofile 65536; events { #worker_rlimit_nofileの値を3で割った数 worker_connections 21800; } このworker_rlimit_nofileの値は、woeker_processesの数によって変わるので注意が必要です。 今回のコンテナはCPUが1個でprocess数も1つの想定だったので、ulimit値とイコールにしています。 ちなみになぜ当初worker_rlimit_nofile値を180000にしていたのかについてですが、fargateコンテナでcat /proc/sys/fs/file-maxコマンドを叩き、「OSのファイルディスクリプタの最大数」として表示された数375274の2で割った数を設定していたからでした。 Fargateではその考え方は通用せず、タスク定義のulimits値=「1プロセスのファイルディスクリプタの最大数」が優先される、ということですね。 ちなみにFargateコンテナ上でulimit -Sn(ソフトulimitを確認するコマンド)を叩いたところ、確かに65536となっていました。 簡単にファイルディスクリプタ関連の用語についてまとめますと 用語 意味 ファイルディスクリプタ OS上でファイルに振られる番号で、ファイルを識別するための目印 OSで扱えるファイルディスクリプタ上限 OSで開くことのできる最大ファイル数。cat /proc/sys/fs/file-maxで確認可能 ソフトulimit 1プロセスあたり使用できるファイルディスクリプタの上限。一般ユーザーも設定可能(ただしハードulimitの数値以下まで)。ulimit -Snで確認可能 ハードulimit 1プロセスあたり使用できるファイルディスクリプタの上限。rootユーザーのみ設定可能。ulimit -Hnで確認可能。 worker_rlimit_nofile Nginxで設定するパラメータ。1workerあたりで開ける最大ファイル数を設定する。 ちなみに余談ですがFargateではタスク定義でulimit値を設定してやらないとデフォルトで以下の値に設定されますので気をつけましょうね。 ソフトulimt 1024 ハードulimt 4096 感想 やはりFargateは奥深い・・・。
- 投稿日:2022-01-27T22:49:06+09:00
FargateでNginxコンテナをデプロイする時、「worker_rlimit_nofile」の値はタスク定義で設定したulimits値以下にしなくてはならない
タイトルのままです。 概要 もうタイトルで伝えたいことは書ききったのですが、せっかくなので経緯を述べておきます。 AWS FargateでNginxとLaravelコンテナをデプロイしていました。 以前、パフォーマンスチューニングでNginxのconfigファイルの設定について、こちらの記事を参考にゴニョゴニョしていたのですが、それからしばらくたった後、あることに気づきました。以下はfargateにNginxコンテナをデプロイした直後のコンテナログです。 [alert] 29#29: setrlimit(RLIMIT_NOFILE, 180000) failed (1: Operation not permitted) なんとworker_rlimit_nofileの設定が失敗している!? 原因追求したところ、どうやら上で設定している180000という数字がよくなかったようです。 原因 Fargateにコンテナをデプロイするには、「タスク定義」を設定する必要がありますが、このタスク定義で設定していたulimits値を超えていたことが原因でした。 task-definition.json(抜粋) "containerDefinitions": [ { "ulimits": [ { "name": "nofile", "softLimit": 65536, "hardLimit": 65536 } ], } ここでulimits値をソフト/ハード共に65536に設定しているので、worker_rlimit_nofileの値は"65536以下"にする必要があるようです。 nginx.confファイルを再設定後、無事にこのエラーは解消されました。 nginx.conf #worker_rlimit_nofile 180000; コメントアウト worker_rlimit_nofile 65536; events { #worker_rlimit_nofileの値を3で割った数 worker_connections 21800; } このworker_rlimit_nofileの値は、woeker_processesの数によって変わるので注意が必要です。 今回のコンテナはCPUが1個でprocess数も1つの想定だったので、ulimit値とイコールにしています。 ちなみになぜ当初worker_rlimit_nofile値を180000にしていたのかについてですが、fargateコンテナでcat /proc/sys/fs/file-maxコマンドを叩き、「OSのファイルディスクリプタの最大数」として表示された数375274の2で割った数を設定していたからでした。 Fargateではその考え方は通用せず、タスク定義のulimits値=「1プロセスのファイルディスクリプタの最大数」が優先される、ということですね。 ちなみにFargateコンテナ上でulimit -Sn(ソフトulimitを確認するコマンド)を叩いたところ、確かに65536となっていました。 簡単にファイルディスクリプタ関連の用語についてまとめますと 用語 意味 ファイルディスクリプタ OS上でファイルに振られる番号で、ファイルを識別するための目印 OSで扱えるファイルディスクリプタ上限 OSで開くことのできる最大ファイル数。cat /proc/sys/fs/file-maxで確認可能 ソフトulimit 1プロセスあたり使用できるファイルディスクリプタの上限。一般ユーザーも設定可能(ただしハードulimitの数値以下まで)。ulimit -Snで確認可能 ハードulimit 1プロセスあたり使用できるファイルディスクリプタの上限。rootユーザーのみ設定可能。ulimit -Hnで確認可能。 worker_rlimit_nofile Nginxで設定するパラメータ。1workerあたりで開ける最大ファイル数を設定する。 ちなみに余談ですがFargateではタスク定義でulimit値を設定してやらないとデフォルトで以下の値に設定されますので気をつけましょうね。 ソフトulimt 1024 ハードulimt 4096 感想 やはりFargateは奥深い・・・。
- 投稿日:2022-01-27T20:52:01+09:00
Step Functions で States.ReferencePathConflict が起きたときの対処
概要 Step Functions の ResultPath を指定したものの、以下エラーが発生することがある。 { "error": "States.ReferencePathConflict", "cause": "Unable to apply ReferencePath $.someTaskResult to input \"input1\"" } ここでは someTaskResult という key に結果を出力しようと試みている。 原因 ステップの入力が Object 型ではない可能性がある。 例えば、プリミティブな String が入力された場合、当然ながら someTaskResult という key は設定できない。例えば Map を使う場合、イテレーションの対象として List を使わなければいけないが、List の各値がプリミティブ型だった場合、イテレータに渡る入力としてこのような事態が起こりうる。 対策 前段の出力を加工し、Object 型にしてしまえばよい。具体的には Parameter が使える。上述の Map による問題だった場合も、Map に Parameter が利用できる。イテレータへの入力が Parameter によって加工された値になる。 Mapの例 "Type": "Map", "Parameters": { "input1.$": "$$.Map.Item.Value", : }, "Iterator": { "States": { "SomeTask": { "ResultPath": "$.someTaskResult", : 上記のようにすると、 { "input1": "~~~" } という入力になるので、 SomeTask の出力 .someTaskResult はエラーなく入力の Object に追加されるようになる。
- 投稿日:2022-01-27T20:32:24+09:00
複数の AppFlow を実行するワークフローを書いた
概要 とある案件で AWS の AppFlow を複数件スケジュール実行したいという話があった。 運用コストを極力抑えたかったので、サーバレスの Step Functions を使ってワークフローを書いた。また、本稿では記載していないが、スケジュール実行部分に関してはセオリー通り EventBridge を用いた。 ステートマシンの全体像 親 特に複雑なことはしておらず、実行対象のフロー (ここではバックアップ処理を行うフロー) の一覧を取得し、あとは Step Functions の Map を使って逐次処理しているのみ。一覧取得は若干複雑な条件を利用してフィルタリングしているため、 Lambda で実装している。 Run AppFlow は別のステートマシンであり、いわゆるネストされたステートマシンとなっている。理由としては、後述するステートマシンのイベント数上限を回避しやすくするため。 子 AppFlow の実行と、終了確認を一定時間ごとに行っている。数時間かかるような長いフローだとポーリングする回数が増大してしまい、結果として Step Functions のイベント数クオータ (25,000 events) に達してしまうため、親でひとまとめでやらずにステートマシンを子に分割してクオータに達しにくくしている。 特に Lambda は利用しておらず、Step Functions の SDK 統合機能を使って appflow:StartFlow や appflow:DescribeFlow を呼び出している。 Whether Flow Ended は Step Functions の Choice を使い、DescribeFlow の LastRunExecutionDetails.MostRecentExecutionStatus が InProgress: Wait へ Successful: Flow Successful へ それ以外: Flow Error へ それぞれ移行するように制御している。 まとめ ほとんどの処理を Step Functions に任せられることができた。サーバレスであるため運用の手間がなく、また料金面も格安で利用が可能。 Step Functions の SDK 統合機能が強すぎる。
- 投稿日:2022-01-27T20:26:36+09:00
電子署名の仕組みについて
内容 この記事はAWS初学者を導く体系的な動画学習サービス 「AWS CloudTech」の講座を参考に作成しました。 https://aws-cloud-tech.com 以下に電子署名の仕組みとそれを実現するための技術である一方向ハッシュ関数について記載します。 電子署名とは ・「電子データ作成者」情報を電子データに付与し、電子ファイルが改ざんされていないことを証明する技術です。 ・紙の書類におけるサインや押印を電子的に実現したものになります。 一方向ハッシュ関数とは ・電子署名を実現するために用いられる暗号化技術です。 ・対象のデータから特殊技術によりランダムな英数字(ハッシュ値:長さは固定)を生成することができます。 ・対象のデータが1ビットでも異なるとまったく別のハッシュ値が生成されます。 ・ハッシュ値から対象のデータを生成することは現実的ではありません。 電子署名の仕組み 署名者(Aさん)は、電子ファイルのハッシュ値を計算し、Aさんの秘密鍵で暗号化します。 上記の電子ファイル、暗号化したハッシュ値、Aさんの証明書の3点を受信者に送信します。 受信者は、Aさんの証明書に含まれるAさんの公開鍵を用いて暗号化したハッシュ値を復号し、電子ファイルのハッシュ値と比較します。 比較した結果が一致すれば、電子ファイルはAさんが作成し、改ざんされていないことが証明できます。 Aさんの秘密鍵はAさんしか持っておらず、Aさんの公開鍵とペアになっているため、復号できたということは、上記の電子ファイルはAさんが作成したものだ、ということが分かると思います。 (参考)AWSにおける証明書発行サービスについて ・AWS環境で利用できるSSL/TLS証明書を発行・管理してくれるサービスとして、ACM(AWS Certificate Manager)があります。 ・証明書の更新はAWSが自動で行なってくれます。 ・無料で証明書を発行できます。 ・コンソールから数分で発行でき、複数の証明書を一括管理できます。 ACMの使用については、以下の記事をご覧ください。
- 投稿日:2022-01-27T20:09:21+09:00
AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID の有無による挙動の違い
概要 Step Functions でネストしたステートマシンを定義する場合、子のステートマシンを呼び出す際に AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID を渡すのが一般的。 "States": { "Run Another State Machine": { "Type": "Task", "Resource": "arn:aws:states:::states:startExecution.sync", "Parameters": { "StateMachineArn": "arn:aws:states:ap-northeast-1:...", "Input": { "AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID.$": "$$.Execution.Id", : なぜ渡さなければいけないのか、ドキュメントを読んでもよくわからなかったので、実際に試してみた。 実行結果 結論としては、子のステートマシンの実行結果の Started By の有無が差異としてあった。 AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID あり Started By に呼び出し元 (親ステートマシン) の arn がある。 AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID なし Started By がそもそもない。 まとめ AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID を渡すと、子の実行結果に Started By が追加される。 AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID を渡さなくても実行自体は問題なく行われる。
- 投稿日:2022-01-27T19:59:13+09:00
AWS認定クラウドプラクティショナー資格】⑨請求サービス
はじめに 今回は、AWSの「請求サービス」の概要について勉強した内容を紹介します。 「請求ダッシュボード」「マルチアカウントの運用」「AWSサポートプラン」「その他の請求サポートツール」に絞って、その特徴をまとめていきます。 参考書籍 ※ 『AWS認定資格試験テキスト AWS認定クラウドプラクティショナー』 本記事は、本書の第9章に相当 項目 請求ダッシュボード マルチアカウントの運用 AWSサポートプラン その他の請求サポートツール 1. 請求ダッシュボード ダッシュボードから、どのサービスにいくらのコストが発生しているのかを確認できます。 請求書については、月の途中でも確認できます。 (1)コストエクスプローラー(AWS Cost Explorer)とコスト配分タグ なんの目的でそのサービスをどのくらい使ったのかを確認するものとして、「コストエクスプローラー」と「コスト配分タグ」というものがあります。 コストエクスプローラー、はリソースの使用状況と、コストを可視化して分析できるサービスです。 AWSサービスの使用量、その使用量に対するコストなどのデータを分析して今後の対策に活かすことができます。 現在利用している、サービスごとの利用料金や使用量などAWSサービスごとの比較をすることができます。そのため、今後も必要などうかの判断をすることが可能となります。 タグとは、ユーザーまたはAWSがリソースに割り当てるラベルのことです。 各タグは、キーと値から構成されます。 タグキーは、リソースごとにそれぞれ一意である必要があります。また、各タグキーに設定できる値は1つのみです。 タグを使用してリソースを整理し、コスト配分タグを使用してコストを詳細レベルで追跡できます。 コスト分配タグを有効化した後、AWSコストを分類して追跡しやすくするために、AWSはコスト分配タグを利用してコスト分配レポート上でコストを整理します。 (2)請求アラーム Cloud Watchメトリクスで請求金額を確認することができます。 アラームを設定すると、アクションを実行することができます。 SNSと連携すれば、特定の金額を超えた時にメール送信することができます。 この請求アラームのサービスはよく使われているもので、これにより、使いすぎを抑止することができるのです。 設定予算を超えると予測された時にアラートを発信するAWS Budegetsというサービスもあるので、これを組み合わせて使うと、効率良いコスト管理ができるようになります。 コストと使用状況レポートを設定すると、アカウントとそのIAMユーザーが使用した各サービスカテゴリのAWS使用状況が、時間単位または日単位の明細項目として記録できます。 また、使用状況のデータを日単位または時間単位で集計することも可能です。 2. マルチアカウントの運用 AWSのアカウントは、個人や組織で一つしか所有できないということはなく、複数作成することができます。 環境を分けたい場合や、用途によって分けたい場合にアカウントで分離することがあります。 AWS Organizations こちらは、複数のアカウントを階層に分けて一括管理できるサービスです。 アカウントグループに複数のアカウントを参加させることで、グループ単位でのポリシー集中管理をすることができ、複数アカウントに対する一括請求(コンソリデーティッドビリング)も行えます。 一括請求を使わない場合は、個々のアカウントにクレジットカードの設定をし、それぞれ請求されることになります。 一括請求により、複数アカウントでリザーブドインスタンスが使えるようになったり、複数アカウントの合計使用量によるボリュームディスカウントを受けられる可能性というメリットがあります。 3. AWSサポートプラン AWSには4つのサポートプランがあります。 適切なサポートプランを選ぶことにより、運用の安全性や効率性を高めることができます。 (1)ベーシックプラン ・AWSアカウントを作ったときに提供されている無料のサポートプラン ・技術サポートは、AWSサービスの稼働状況をモニタリングしているヘルスチェックについてのサポート ・Trusted Advisorは最低限必要な項目のみ (2)開発者プラン ・29USDか使用量3%の大きい方 ・技術サポートを作成できるユーザーは1ユーザーのみ(9:00~18:00) ・構成要素についてのアーキテクチャサポート ・Trusted Advisorは最低限必要な項目のみ ・ケース重要度と応答時間は、一般的なガイダンス(24時間以内)、システム障害(12時間以内) (3)ビジネスプラン ・100USDか使用量に応じた計算式の大きい方 ・技術サポートを作成できるユーザーは無制限(24時間体制) ・アーキテクチャはユースケースガイダンス ・Trusted Advisorは全項目 ・サポートAPIの使用可 ・サードパーティーソフトウェアのサポート ・ケース重要度と応答時間は、開発者プランに加え、本番システムの障害(4時間以内)、本番システムのダウン(4時間以内) (4)エンタープライズプラン ・15,000USDか使用量に応じた計算式の大きい方 ・技術サポートを作成できるユーザーは無制限(24時間) ・アプリケーションのアーキテクチャサポート ・Trusted Advisorは全項目 ・サポートAPIの使用可 ・サードパーティーソフトウェアのサポート ・テクニカルアカウントマネージャー ・サポートコンシェルジュ ・ホワイトグローブケースルーティング ・管理ビジネス評価 ・ケース重要度と応答時間は、ビジネスプランに加え、ビジネスクリティカルなシステムダウン(15分以内) AWSには、APN(AWSパートナーネットワーク)があります。 主に、AWS上での設計・開発・構築・移行・管理などの支援を提供するコンサルティングパートナーと、AWSに統合されたSaaSや接続サービスなどを提供するテクノロジーパートナーがあります。 また、専門家からなるグローバルチームがAPNパートナーと協力して支援するAWSプロフェッショナルサービスもあります。 4. その他の請求サポートツール (1) AWS Princing Calculator AWSでどれくらいのコストがかかるのかを事前に知るためには、AWS Princing Calculatorを利用します。 AWSの各サービスを選択でき、そのサービスを使用する予定のリージョンを選択することができます。 クイック見積もりも可能です。 サービスによっては、無料利用枠も含めた計算も可能です。 こちらは、マネジメントコンソールにログインしなくても使えます。 (2)TCO計算ツール こちらは、AWSへの移行、導入を検討している際に、従来のオンプレミスの環境でかかるコストとAWSへ移行した場合のコストが比較できます。 こちらも、マネジメントコンソールにログインしなくても使えます。 ○設定可能な項目 ・通貨単位 ・CPU、メモリ、ディスク容量、OS、ハイパーバイザー ・自己所有か他社データセンターか ・ネットワーク転送量 ・利用予定バージョン ・データセンター運用費用 ・専用サーバーか共有サーバーか ・物理サーバーか仮想サーバーか ・データベースエンジン 参考サイト ●AWS Cost Explorerとは?コストを可視化し分析 ●AWS Organizations とは? ●AWS Organizationsで開発の安全性と生産性を同時に向上する ●1アカウントでAWSを利用している場合のAWS Organizations化について ●【ざっくり解説】コスト管理できるサービスの特徴や違い 参考書籍 ※ 『AWS認定資格試験テキスト AWS認定クラウドプラクティショナー』 ● Amazonはこちら ● 楽天はこちら
- 投稿日:2022-01-27T19:26:58+09:00
Laravel sail AWS S3 画像をアップロードする
【Solved】 Laravel sail 本番環境で画像投稿 500 error はじめに Laravel 初学者の私が学習した内容をアウトプットしていく記事になります。 冗長している点や軽い書き方などあれば御指南お願いいたします。。。 前提条件 ・PHP ・Laravel sail ・Heroku ・AWS S3 エラー " Missing required client configuration options: region While Trying to Implement S3 " と本番環境で画像投稿を試みたが、上記のエラーが出てきた。 要は、「 画像を上げる際にクライアント設定オプションがない 」 と注意された。。。 ローカル環境では上手くいっていたのに、本番環境でなんで!? 解決策 答えは、ものすごく単純、、、 デプロイ ( 今回は Heroku )にconfig:set( AWS )を忘れていたため。凡ミスてか詰めが甘い。 ローカル環境では、.envにそれぞれを設定していたためローカルでは正常に動作 .env AWS_ACCESS_KEY_ID={アクセスキー} AWS_SECRET_ACCESS_KEY={シークレットアクセスキー} AWS_DEFAULT_REGION=ap-northeast-1(東京の場合) AWS_BUCKET={バゲット名} しかし、.envファイルは隠しファイルなのでリリースしようが反映されない。 なので、Heroku に各情報を入れなければならない。 あとは、セットするだけです。簡単。 heroku config:setまたは、アプリ内で直に書いてセットするだけでした。 完了したら、Web Applicaton Debud Modeをfalseに直しておきましょう!! まとめ エラーのまとめ記事になりますので、記録用として書かせていただきました! 調べていたら、php artisan config:cacheしたら直ったなどの記事をいくつか見受けましたが、あまりオススメはしません!! ファイルの役割を理解して取り組むことが大事ですね。(切実に) ご拝読ありがとうございました!!
- 投稿日:2022-01-27T18:17:02+09:00
Amazon Elastic Block Store(EBS)自分用まとめ
テストでEC2を立ち上げてしばらくしたら、メールでEBSの無料利用枠がもうすぐ終了するとの連絡が来た。 EC2は1ヶ月立ち上げたままでも新規特典で無料で利用できると思っていた為、急いで調べた。 ◎結論 EC2を立ち上げると自動でストレージとしてEBSが起動し、立ち上げた時間分課金されることがわかった。 ◎公式サイト Amazon EBS ボリュームは、GB/月 (GB-月) 単位で請求されます。この GB/月は、お使いのアカウントにプロビジョンされている EBS ストレージのギガバイト数と、この EBS ストレージがアカウントにプロビジョニングされた期間に基づいて計算されます。 ストレージが使用されていない場合でも、アカウントにプロビジョニングされたストレージの総量に対して請求されます。例えば、1 か月で 100 GB の EBS ボリュームをプロビジョンし、そのボリュームに 1 GB のデータしか保存しなかったとしても、100 GB/月の EBS ストレージの料金が請求されます。 Amazon EBS ストレージの請求金額を最小限に抑えるには、次の操作を実行します。 アクティブな状態で使用していないボリュームのスナップショットを作成します。 不要になったスナップショットを削除します。 EBS ボリュームを監査して、ボリューム内のストレージの大部分が使用されているか確認します。使用されていなければ、もっと小さい EBS ボリュームにデータを移行します。 EC2にアタッチされておらず孤立したEBS ボリュームは、アタッチされていない間も料金が発生します。 ◎AWS EBSとは? Amazon Elastic Block Store(EBS)は高機能なストレージサービス。 EBSはAmazonEC2に限らず、データベースや、エンタープライズアプリケーション、コンテナ化されたアプリケーションなど、多くのサービス向けに提供されている。 「Amazon EC2」との関係性 AWSにおいて、Elastic Compute Cloud(EC2)とEBSは仮想サーバとHDDの関係にあります。EC2はAWS上に仮想サーバを作成するサービスです。EBSはEC2インスタンス用に準備された仮想ディスク。 EC2のデータはすべてEBSに保存されるよう構成することが基本。 EC2にもデータを保存することはできるが、EC2だけでは、EC2を停止すると保存したデータが失われるので EC2を停止してもデータが消えない永続的なブロックストレージボリュームであるEBSを使う。 「Amazon S3」との違い EBSは主に、EC2インスタンスにマウントして、ローカルストレージとして利用できるブロックストレージとして利用されます。それに対し、Amazon S3は、安全にどこからでも接続できるオブジェクトストレージとして利用されます。 特徴 2つのディスクタイプ Amazon EBSには、SSDタイプとHDDタイプの2種類のディスクタイプが存在する。 SSDタイプのディスクは、I/Oサイズが小さく、読み書きの頻度が高いシステムに適しています。Amazon EC2インスタンスのデフォルトのEBSボリュームタイプであるgp2もSSDタイプのディスクです。HDDタイプのディスクは、バックアップやストリーミングなどのI/Oサイズが大きく、高スループットが要求されるシステムに適しています。 EBS Snapshot機能 EBSには、データのポイントインタイムスナップショットをAmazon S3に保存する機能が用意されている。 スナップショットとは、簡単に言うとバックアップです。 ある時点でのサーバーのディスク状態を丸ごと保存した、ファイルやフォルダのことを指します。 丸ごと保存するので、データやソフトウェアだけでなく、OSや設定情報などすべてを含みます。 EBSスナップショットは、S3に格納されます。 その為、スナップショットを保持している期間はS3の料金がかかります。 (中略) 定期的にEBSスナップショットを取得していれば、インスタンスのコピーを作る場合にAMIイメージを作成し、新しいインスタンスを複製することができます。 その他の特徴、解説は参考サイトを参照すること... ◎ブロックストレージサービスとは? Amazon EBSはストレージサービスであり、Amazon EBSを利用することによってデータを保管することができます。 Amazon EBSが提供するストレージは「Amazon EBSボリューム」または単に「ボリューム」と呼ばれ、AWSの仮想マシンサービスであるAmazon Elastic Compute Cloud (EC2)のインスタンス(仮想マシン)にAmazon EBSボリュームを割り当てることができます。 なお、Amazon EC2インスタンスにAmazon EBSボリュームを割り当てることを「アタッチ」と呼び、反対にAmazon EC2インスタンスからAmazon EBSボリュームの割り当てを解除することを「デタッチ」と呼びます。 Amazon EC2インスタンスは自身にアタッチされたAmazon EBSボリュームにアクセスすることができ、通常はext4などのファイルシステムを構築しファイル単位でデータを読み書きします。 また、Amazon EC2インスタンスを起動するためのOSもAmazon EBSに格納され、OSが格納されたAmazon EBSボリュームを作成する場合には「Amazon Machine Image」(AMI)と呼ばれるAmazon EBSボリュームのテンプレートが使用されます。 料金体系 1ヵ月にプロビジョニングされたストレージ1GBあたりに所定の利用料(ボリュームの種類によって単価は異なる)が発生する Amazon S3やAmazon EFSとの違い AWSはAmazon Simple Storage Service (S3)やAmazon Elastic File System (EFS)などの他のストレージサービスも提供しており、データを保管するという意味においてはAmazon EBSと共通しています。 しかしながら、これらのサービスが提供するストレージはAmazon EBSが提供するストレージとは種類が異なり、それぞれアクセス方法などに違いがあります。 まず、Amazon S3は「オブジェクトストレージ」と呼ばれる種類のストレージであり、HTTPSエンドポイントへアクセスしてオブジェクト単位でデータを読み書きします。 一方、Amazon EFSは「ファイルストレージ」と呼ばれる種類のストレージであり、NFSでマウントしてファイル単位でデータを読み書きします。 これらのストレージに対し、Amazon EBSは先に述べたように「ブロックストレージ」であり、Amazon EC2にアタッチしてブロック単位でデータを読み書きます。 Amazon S3やAmazon EFSではなくてAmazon EBSを選択するべき場合としては、例えばWebDAVのようにPaaSとして提供されないストレージを必要とする状況でAmazon EC2インスタンスを使用して自ら構築・運用する場合、Amazon EC2インスタンスにアタッチするブロックストレージとしてAmazon EBSが利用されます。 各種のストレージにはそれぞれ向き不向きがあり、要件などを考慮してどの種類のストレージを使うべきかを十分に検討することが重要です。 使わないEC2インスタンスはTerminateする 利用していないEC2をSTOPした場合でもEBSの利用料はかかる。 EC2は停止していればほとんどお金かからないイメージがあるかもしれないがそんなことはない。使わないEC2インスタンスはStopではなくTerminateしよう。
- 投稿日:2022-01-27T17:30:49+09:00
LaravelでのAmazonSES/SMTP設定
経緯 LaravelからAmazon SESへの接続がタイムアウトしたりエラーになって試行錯誤したときのメモです。 環境は下記の通り。SESはAPI経由でもよいですが、ひとまずSMTPで設定してみることにしました。 基盤構成: EC2 → Amazon SES PHPフレームワーク: Laravel 8.x 試行錯誤してるときに出たエラーたち いずれもポートの設定などを誤っているために出力されていたものです。 (Swift_IoException(code: 0): Connection to tcp://email-smtp.ap-northeast-1.amazonaws.com:465 Timed Out at /***********************/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php:166 ERROR: Expected response code 220 but got code "", with message ERROR: Failed to authenticate on SMTP server with username "***********" using 2 possible authenticators. Authenticator LOGIN returned Expected response code 334 but got code "530", with message "530 Must issue a STARTTLS command first. Amazon SESの画面 先達の知恵を借りつつもAWSドキュメントなどにあたって調べてみたものの何が問題かがぱっとわからず。 AWSコンソールのデザイン変更で、参考例のキャプチャの項目が見当たらず困るのは日常茶飯事ですが、 今回もSMTPの設定項目がどこにあるかがわからず時間を取られました。 2022/01現在のコンソール設定では「Account dashboard」の中段に、エンドポイントやポートが表示されている模様です。 EC2では25番ポートはデフォルトで使用できず、申請が必要になるので、他のポートを使用することにしました。 SMTPで接続したいIAMユーザ設定がまだない場合は「Create SMTP credentials」から、ユーザ名を指定するだけで簡単にID/PWの接続情報を作成できます。 PORTとENCRYPTIONの関係性 試行錯誤したのは結局ここでした。 STARTTLSのポートでは tls 、TLSのポートでは ssl で指定するとうまくいきそうでした。 MAIL_PORT MAIL_ENCRYPTION 465 ssl 2465 ssl 587 tls 2587 tls Laravelの.env設定例 EC2からセキュリティグループのアウトバンドで対象ポートを絞っていなければ、下記の設定で疎通できました。 MAIL_DRIVER=smtp MAIL_HOST=email-smtp.ap-northeast-1.amazonaws.com MAIL_PORT=465 MAIL_ENCRYPTION=ssl または MAIL_DRIVER=smtp MAIL_HOST=email-smtp.ap-northeast-1.amazonaws.com MAIL_PORT=587 MAIL_ENCRYPTION=tls 書き換えたあとは設定キャッシュをリフレッシュして反映し、疎通成功です。 php artisan config:cache
- 投稿日:2022-01-27T16:33:53+09:00
ヘルプデスクへのメール到達確認の問い合わせ
ヘルプデスク宛によくシステムからのメールが届かない、メールが正常に送信されたか調べて欲しいなどのお問い合わせがよくあります。 そんなときの対応方法をまとめました。 1.メールアドレスに不備がないか確認 メールアドレスとして正しくない。スペルが間違っている場合があるので、確認します。 2.メール送信ログを確認 まずメールログを調べます。 当社では、AWSのCluodWatch Logsで収集しています。 AWSにはCloudWatch Logsというマネージドサービスがログ収集を行う機能として備わっています。 AWSのCluodWatch Logsでのメールログは以下のメニューから確認します。 CloudWatch>ログ>ロググループ>ログストリーム選択 ログイベントのイベントをフィルター項目に調べたいメールアドレスを入力します。 送信されるべき日時も分かればCustom項目から日時を絞って検索することもできます。 該当するメール送信ログの中でstatusと書かれたところを確認します。 メールログ フォーマット Jan 28 12:22:19 //処理の発生日時 mta13a //ホスト名 postfix/smtp[13557]: //プロセス名 9005E823A66: //キューID to=xxx@docomo.ne.jp, //送信先メールアドレス情報 relay=mfsmax.docomo.ne.jp[xxx.xxx.xxx.xxx]:25, //送信先SMTPサーバ情報 delay=0.35, delays=0.09/0/0.07/0.2, //メール送信の処理時間 dsn=2.0.0, //SMTPステータスコード status=sent //送信結果 statusの種類には以下の3つがあります。 status=sent 送信完了 status=bounce 送信失敗 status=deferred 送信リトライ 3.メール送信ログの内容をお伝えする sentの場合の対処法 sentになっていれば、メールサーバーから正常に送信されています。 こちらからは正常に送信されているため送信先のメールサーバ管理者の方にMessage-Id を伝えて、送信先側で調べてもらうしかないです。 deferredの場合 deferredは、何らかの原因で再送がかかっている状態です。 エラーコードを見て内容を確認します。(相手のメールボックスが一杯、相手サーバーが障害を起こしている、など色々) 相手先のサーバーの問題が解消すれば到達します。 例)Host or domain name not found. Name service error for name=xxxx.net type=MX: Host not found, try again →相手サーバば見つかりません。 bounceの場合 bounceは何らかの原因でメールが戻ってきている状態で相手には到達していません。 たいていはメールアドレスが間違っているか、迷惑メールに分類されていることが多いです。 迷惑メールに分類されてスパム扱いされている場合はプロバイダに連絡して解除してもらいます。 ログにGoogleのMTAが表示されている場合は以下を案内します。 Google管理者ヘルプページに書いてある手順でメールログを確認して******もらう。 Google 管理者ヘルプページ Googleのメールのフィルタを設定してもらう Googleメールの設定ボタン(歯車)>「すべての設定を表示」>「フィルタとブロック中のアドレス」 リストの一番下の方にある「新しいフィルタを作成」でFrom: に「ブロックを解除したいメールアドレス」を入力 「フィルタを作成」をクリックし「迷惑メールにしない」にチェックし「フィルタを作成」をクリックして作成する 以上、ヘルプデスクへのメール到達確認の問い合わせ対応方法でした。何かの参考になれば幸いです。
- 投稿日:2022-01-27T16:22:21+09:00
AWS Lambda は、Amazon SQS、Amazon DynamoDB、Amazon Kinesis をイベントソースとするイベントフィルタリングをサポートしました
はじめに AWS Lambda は、イベントソースとして SQS、DynamoDB、Kinesis のコンテンツフィルタリングオプションを提供するようになりました。イベントパターンのコンテンツフィルタリングでは、お客様が指定したフィルタリング条件の下で、SQS、DynamoDB、Kinesis からのみ Lambda 関数がトリガーされるような複雑なルールを書くことができます。これにより、お客様の Lambda 関数へのトラフィックを減らし、コードを簡素化し、全体的なコストを削減することができます。 お客様は、SQS、DynamoDB、Kinesis をトリガーとする Lambda 関数のためにイベントソースマッピングを作成または更新する際に、最大 5 つのフィルター条件を指定することができます。フィルターの組み合わせは、デフォルトでは OR 論理で行われます。つまり、定義されたフィルタリング条件のいずれかに合致するイベント/ペイロードは Lambda 関数のトリガーに渡され、フィルタリング条件のどれにも合致しないイベント/ペイロードはドロップされます。この機能により、利用可能なイベントのサブセットのみを使用するマイクロサービスの関数呼び出しを減らし、対象となる Lambda 関数やダウンストリームアプリケーションがフィルタリングを実行する必要がなくなります。 コンテンツフィルタリングは、AWS Lambda が利用できるすべての商用リージョンで利用可能です。この機能を使用するために、AWS Lambda の標準料金以上の追加費用はかかりません。 この機能の詳細については、イベントフィルタリングのための AWS Lambda ドキュメントをご覧ください。 の記事の更新内容を確認してみました。 どんな更新 Lambdaのトリガに設定したSQS、DynamoDB、Kinesisに対しフィルタリング条件を設定することで、無駄なLambda呼び出しを減らすことが出来るようになった。 これまでは 呼び出されたLambda側でフィルタリングしてあげる必要があった。 なにがうれしいか Lambdaを呼び出す前にフィルタリングすることで、Lambda側のフィルタリングロジックがなくなる Lambdaの呼び出し回数が減ってお財布にやさしい 料金は Lambdaにかかる通常料金以外に追加費用はなし やってみる Labmda側フィルタリング条件 ProductName要素が存在する場合、Lambdaが発火するように指定 SQSメッセージ ProductName要素が存在するメッセージを送信する 適当なSQSを作成します。 適当なLambda1を作成します。 トリガーを追加して...... 追加の設定を開き、フィルタリング条件を設定します。 フィルタリング条件については を参考に。 今回はSQSから送信するメッセージのJSON構造が SQSから送信するメッセージ { "DataName": { "messageAttributes": {}, "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", "eventSource": "aws:sqs", "eventSourceARN": "arn:aws:sqs:us-east-2:123456789012:my-queue", "ProductName": "product name aruyo" } } であるため、フィルタリング条件を Lambdaフィルタリング条件 { "body": { "DataName": { "ProductName": [ { "exists": true } ] } } } のように設定します。 追加すると、以下のようにフィルタリング条件が確認できます。 これで準備は完了です。 では、メッセージを送信してみましょう。 メッセージ本文にメッセージjsonを指定してメッセージを送信すると...... Lambdaが動作したことが確認できました。2 まとめ LambdaのトリガにSQS、DynamoDB、Kinesisを利用する&特定の条件に一致した場合のみ動作させたいという場合、こちらの機能を思い出しましょう。 さいごに Lambdaのフィルタリング条件にデータプロパティを指定するとき、イベントソース(SQS, DynamoDB, Kinesis)によってデーターキーを変える必要があります。 SQSの場合bodyになる { "body": { "Data1": [ pattern ] } } dynamodbの場合dynamodb { "dynamodb": { "Data1": [ pattern ] } } Kinesisの場合data { "data": { "Data1": [ pattern ] } } この形式で設定しないとうまく動かないので注意しましょう。3 参考 ログに受け取ったjsonデータを吐くだけのLamda ↩ CloudWatch logsのログで動作確認 ↩ ハマりました ↩
- 投稿日:2022-01-27T16:16:50+09:00
DBとOpensearch連携手順書
⓪事前準備 AWS aurora(別のエンジンでもOK)・EC2(OS:Amazon Linux、IAMロール→セキュリティグループは適宜お願いします)・OpensearchをAWSコンソールで作成 ①EC2にSSHログイン ②EC2にmysqlコネクタをインストール 参考:https://qiita.com/ponsuke0531/items/3ae69a9d477809c00917 ③データベースとテーブルをEC2経由で作成 ※以下を実行する前にEC2にcsvファイルをインポートすること ログイン→作成→切り替え→設定変更→テーブル作成→ロード→確認 mysql -h (データベースのエンドポイント) -P 3306 -u admin -p --enable-local-infile CREATE DATABASE sampledb; use sampledb; SET character_set_database=utf8mb4; SET character_set_server=utf8mb4; create table sampledb (name varchar(10), type varchar(10), resource varchar(10), place varchar(10), sub varchar(10)); load data local infile "/home/ec2-user/sampledataset.csv" into table sampletable fields terminated by ','; SELECT * FROM sampletable; ④jdbcコネクタ wget https://dev.mysql.com/get/Do wnloads/Connector-J/mysql-connector-java-8.0.27.tar.gz tar xvzf mysql-connector-java-8.0 .27.tar.gz ⑤logstashとプラグインのインストール(inputプラグインはもともとついてた) ※念のためソースを共有 https://opensearch.org/downloads.html $wget https://artifacts.opensearch .org/logstash/logstash-oss-with-opensearch-output-plugin-7.16 .2-linux-x64.tar.gz $tar xvzf logstash-oss-with-opensearch-output-plugin-7.16.2-linux-x64.tar.gz $logstash-7.16.2/bin/logstash-plugin install logstash-output-opensearch $logstash-7.16.2/bin/logstash-plugin list | grep -E "jdbc|opensearch" OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release. logstash-integration-jdbc tqq logstash-input-jdbc tqq logstash-filter-jdbc_streaming mqq logstash-filter-jdbc_static logstash-output-opensearch ⑥設定ファイル作成 outputの設定のopensearchドメインエンドポイントの後に443ポートを指定しないとデフォルトで9020ポートに接続してしまうので指定必須 logstash_datapipeline.conf input { jdbc { jdbc_driver_library => "/home/ec2-user/mysql-connector-java-8.0.27/mysql-connector-java-8.0.27.jar" jdbc_driver_class => "com.mysql.jdbc.Driver" jdbc_connection_string => "jdbc:mysql://(データベースのエンドポイント):3306/sampledb?useSSL=false" jdbc_user => "admin" jdbc_password => "password" schedule => "* * * * *" statement => "SELECT * FROM sampletable" jdbc_validate_connection => true } } output { opensearch { hosts => ["https://(opensearchドメインエンドポイント):443/"] user => "user" password => "password" index => "sample-%{+yyyy.MM.dd}" } } ⑦データ同期実行 sudo logstash-7.16.2/bin/logstash -f logstash_datapipeline.conf この手順で基本的にはkibanaのindexに反映されるはず エラーメモ 再度bin/logstash -f logstash_datapipeline.confを実行するとエラーになる → プロセスがすでに立ち上がっているため (エラー:Failed to execute action) 対処 ps ax | grep logstash sudo kill -9 25831 コマンド実行できない → パスミスってるかサービス立ち上がっていない 対処 sudo systemctl start logstash sudo systemctl status logstash Couldn't find any output plugin named 'opensearch'. Are you sure this is correct? → プラグインミスってる 対処 $logstash-7.16.2/bin/logstash-plugin list | grep -E "jdbc|opensearch" OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release. logstash-integration-jdbc tqq logstash-input-jdbc tqq logstash-filter-jdbc_streaming mqq logstash-filter-jdbc_static logstash-output-opensearch →これがないと上のエラーになる [ERROR] Failed to install template. {:message=>"Got response code '403' contacting Elasticsearch at URL 'https://(opensearchドメインエンドポイント):443/(存在しない何か)' → 設定ファイルのjdbc_connection_stringが多分間違えているので要確認 参考リンク 実現したいことに近い例: https://www.elastic.co/jp/blog/how-to-keep-elasticsearch-synchronized-with-a-relational-database-using-logstash https://aws.amazon.com/jp/premiumsupport/knowledge-center/opensearch-connect-filebeat-logstash/ logstash-output-opensearch: https://opensearch.org/docs/latest/clients/logstash/index/#install-logstash logstash-integration-jdbc: https://www.elastic.co/guide/en/logstash/current/plugins-inputs-jdbc.html jdbcドライバー:: https://dev.mysql.com/downloads/connector/j/ logstashインストールパッケージ: https://www.elastic.co/jp/downloads/logstash
- 投稿日:2022-01-27T15:49:52+09:00
API Gateway の API バージョン指定(ベースパス)で Lambda の処理を分岐させる
はじめに ある API で v2 と v3 を並行稼働させることになりました URL は以下の想定 https://xxx.com/v2/some_items https://xxx.com/v3/some_items v2 と v3 を個別の REST API やステージとして構築すれば簡単に実装できます しかし、この API では API_KEY を使った使用量制限などを行っているため、 個別に実装してしまうと、 v2 と v3 で API_KEY を別々にしなければなりません 全ユーザー用に新しい API_KEY を発行する必要がある ユーザーは新しい API_KEY を使う必要がある 新旧どちらの API_KEY も発行できるようにシステム改修する必要がある そこで、 v2 も v3 も同じ REST_API 、ステージに設定した上で、 ユーザーがアクセスしてきた URL によって処理を分岐させることにしました これにより、ユーザーは同じ API_KEY のまま URL を変えるだけで移行が可能になります この実装のため、検証した内容を残しておきます 同一リソースへのベースパスマッピング 以下のどちらへのアクセスも同じ API へ繋げなければなりません https://xxx.com/v2/ https://xxx.com/v3/ API Gateway のベースパスマッピングでは、問題なく同一リソースに別のパスを設定できました Terraform では以下のような形になります resource "aws_api_gateway_base_path_mapping" "api-v2" { api_id = aws_api_gateway_rest_api.some-api.id stage_name = aws_api_gateway_stage.some-api.stage_name domain_name = aws_api_gateway_domain_name.some-api.domain_name base_path = "v2" # ここだけ違う } resource "aws_api_gateway_base_path_mapping" "api-v3" { api_id = aws_api_gateway_rest_api.some-api.id stage_name = aws_api_gateway_stage.some-api.stage_name domain_name = aws_api_gateway_domain_name.some-api.domain_name base_path = "v3" # ここだけ違う } API Gateway から Lambda へのベースパス連携 既存の実装では Lambda でベースパス( /v2/ や /v3/ の部分)は取得できませんでした ( /some_items の部分は取得できましたが) そのため、 API Gateway の requestTemplates に以下のようにパス情報を追加しました { ... "path" : "$context.path" } これにより、 Lambda 側で以下のようにベースパスが参照できるようになりました exports.handle = (event, context, callback) => { const path = event.path; ... 以下の AWS 公式ドキュメントを参考にしています おわりに 特殊なケースなのであまり参考にはならないかも、、、 ただ、 Terraform で定義することで、こういうケースでも対応しやすかったとは思います
- 投稿日:2022-01-27T13:39:46+09:00
SAM(CloudFormation)で修正のデプロイしたのにAPI Gatewayの変更が反映されない(REST API)
困っていたこと 既にデプロイ済みのAWS SAMスタックで、開発環境用にCORSの設定を緩める必要があって、API GatewayとLambdaのAllow-Originを*にしようとしました。(API GatewayはREST APIタイプ) sam deployした後、マネジメントコンソールで確認してみると、リソースには変更が反映されている模様。 きちんとAllow-Originが*になっている。 リソース→アクション→CORSの有効化 解決! 先輩のアドバイスで、マネジメントコンソールでAPIを手動でデプロイしてみる。 リソース→アクション→APIのデプロイ これでうまくいきました。 今回は問題は解決されたけど、sam deployしたのにAPI Gatewayだけ手動で再デプロイしないといけないって、一体全体どんな仕様なんだ!? ドキュメントを見てみる REST APIのドキュメントでは、それに近しい、下記のような注意書きが。 また、こんなドキュメントも↓ 今回はマネジメントコンソールでデプロイしましたが、CLIでもできそうですね。 https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/set-up-deployments.html (参考)同じことで困った方々がいらっしゃる模様。 - https://suzuki-navi.hatenablog.com/entry/2020/12/17/214538 - https://qiita.com/gotousua/items/4efcf1ff068fcb83334e
- 投稿日:2022-01-27T12:04:49+09:00
大量データ加工処理の高速化
はじめに 今まで一般的なWeb開発はしてきたけど高速化についてあまり考慮せずに実装してきたエンジニアの方に向けて、筆者の大量データ ( 7億-8億レコード ) 加工処理高速化の経験を基に、本番実行で何を目指すかということと、それまでに実際にどのようなアプローチがあるのかを提案できればと思います。 あくまで提案なので、「こうしたらもっと高速になるよ」的な箇所は多々あるかと思います。 コメントなどでご指摘いただければ幸いです。 本記事における前提条件 本記事における前提条件を筆者の経験した環境を参考に記載します。 本プロジェクトの背景及び要件 既存サービスで蓄積されたデータを外部のシステムに連携して有用活用するにあたってのPoVを実施する。 既存サービスで蓄積されたデータの一部を匿名化 (ハッシュ化) したものをCSVに書き出し、外部のシステムにPOSTする。 本番実行までの実装及び検証は短期間 (2-4週間程度) である。 加工処理はできるだけ早くする完了させる 採用したテクノロジー Ruby on Rails API mode AWS EC2, RDS, Elasticache Redis, CloudWatch データ加工処理高速化のアプローチ 本対応における極意 塵も積もれば山となる 加工処理は要件を満たす範囲内で最速のロジックを追求する 外部接続回数は最小限に抑える 使用するデータサイズをできるだけ小さくする 使いまわせるデータは使いまわす マシンスペックを最大限活用する 実装レベル 計測 高速化実装は実行時間を計測してロジックをチューニングしながら進めます。 今回はRuby標準の benchmark というライブラリを採用しました。 benchmarkの使用方法については細かく解説しないので、以下のような記事を参考にしていただければと思います。 https://qiita.com/scivola/items/c5b2aeaf7d67a9ef310a https://nishinatoshiharu.com/usage-benchmark/ 並列実行 今回のようなデータ量を直列で加工していてはいつまでたっても処理が完了しません。 複数スレッド/プロセスに作業を分担して並列実行します。 今回はRuby Gemsの Parallel を採用しました。 # Parallel.processor_countでCPUのコア数が取得できる csv_data += Parallel.map(records, in_processes: Parallel.processor_count) do |record| # some process end このような記述にすると、 records の要素が record としてブロックに渡され、各プロセスで加工処理できるようになります。 今回のケースにおいて in_thread と in_processes は計測の結果、プロセスに処理させる方が多少高速だったため in_processes を採用しました。 in_thread を使用し、 #some_process 内でDB接続する部分がある場合は、コネクションプールを使用して高速化することも検討できます。 加工処理の高速化 分割抽出 大量なデータを一度にDBから取得しようとするのは非常に非効率です。 find_in_bataches で細切れにデータを取得して高速化を図ります。 SomeModel.find_in_batches(batch_size: Constants::Batch::BATCH_SIZE) do |records| # some process csv_data += Parallel.map(records, in_processes: Parallel.processor_count) do |record| # some process end # some process end *Constants::Batch::BATCH_SIZE は独自に宣言した定数です。最終的に 100_000 で設定しました。 必要な属性のみ抽出 今回CSVには必要な属性のみ書き出すため、抽出する属性も最小限に絞ります。 また、加工対象のテーブルがパーティショニングされている場合は、 SomeModel の部分にパーティションが渡されるような実装になるかと思います。 SomeModel.select_csv_columns.find_in_batches(batch_size: Constants::Batch::BATCH_SIZE) do |records| # some process csv_data += Parallel.map(records, in_processes: Parallel.processor_count) do |record| # some process end # some process end scope :select_csv_columns, -> do select([ :some_colum, ... ]) end 加工に使用されるアルゴリズムなどのチューニング 今回特定の属性を匿名化するため、最初は SHA-512 でハッシュ化していました。 Digest::SHA512.hexdigest("#{string}") 今回ハッシュ化のセキュリティレベルに関して特段指定がなかったため、より高速な SHA-1 に変更しました。 Digest::SHA1.hexdigest("#{string}") 処理速度の比較.1 処理速度の比較.2 インフラレベル 全体像 全体のシーケンス図を描いてみました。 各EC2インスタンスにssh接続し、それぞれのインスタンス内でrakeタスクを実行する形で構成されています。(ここは正直時間が足りず...改善点は多々あると思っています) Rakeタスクのパラメータにデータ抽出のオフセット値を渡し、処理対象を分散するようになっています。 対象テーブルの加工時に、他テーブルへの参照が必要な場合ループ単位で外部参照のSQLが発行されてしまいます。 できる限りDB接続を減少させるため、一度参照したKVはRedisにストアし、値がセットされている場合はそちらを使用します。 また、rakeタスク実行時にはCloudWatchでメモリ使用率やIOPSを監視し、異常が発生したらすぐに対応できる体制を整えます。 さいごに 今回全体での処理経過時間は9時間程度でした。 (EC2 a1.4xlarge:8台, RDS db.t3.medium:1台, Elasticache t2.small:1台) 実行方法に関しての検討はタイムアップで脳筋実行になってしましたが、 処理単位を分割したタスクをキューイングし、各インスタンスがタスクを拾いにくる、という形を作ると処理効率を最大化できそう というアドバイスをいただいたので、次回このような機会があったときには試してみたいと思っています。 その他より良い方法がある方はご意見いただけると幸いです。