TECH PLAY

SCSKクラウドソリューション

SCSKクラウドソリューション の技術ブログ

1141

もしも、映画史に残る感動的な場面を、最新のAI技術で蘇らせることができたら…? こんにちは、佐藤です。 皆さんは、 名作映画 といわれたら何を思い浮かべますか? 私は最近初めて映画 『タイタニック』 を見たのですが、やはり名作といわれるだけありますね…。 結末を知っていても楽しめるのはまさに不朽の名作といわれる所以だと感じました。 さて、タイタニックの中で最も印象的なシーンの一つが、ジャックとローズが船首で腕を広げるシーンですよね。 今回は、 Amazon BedrockでLuma AI の「Ray2」モデルを使い、この有名なワンシーンを再現できるのか―― というお話です。 Ray2モデルとは? 2025年1月23日、AWSは Luma AI の新しい動画生成 AI モデル「Ray2」 が Amazon Bedrock で利用できるようになった と発表しました(参考  https://aws.amazon.com/jp/about-aws/whats-new/2025/01/luma-ais-ray2-visual-ai-model-amazon-bedrock/ )。まずは簡単にLuma AIのRay2モデルについてご紹介しようと思います。 Ray2は、 Luma Labsが開発した最新の動画生成AIモデル です( https://lumalabs.ai/ray )。 前モデルであるRay1と比較して 処理能力が10倍に向上 しており、より滑らかで自然な動きを持つリアルな映像を生成できるのが大きな特徴です。また、従来のAI動画生成モデルであれば数分から数時間かかっていたレベルの動画生成を、 Ray2はわずか1分程度で作成可能 ということで大きな話題を呼びました。 現在はテキストプロンプトから動画生成をサポートしていますが、 今後は画像から動画生成や動画から動画への変換、また作成した動画の編集機能も実装予定 とのことで、これからの動向に目が離せないAIサービスですね。 テキストプロンプトから動画を生成 5秒または9秒のクリップを作成可能 高解像度(1080pのフルHD解像度もサポート)   BedrockでRay2を使ってみよう さて、さっそくBedrockでRay2モデルを使ってみましょう。 事前準備として行うセットアップもそこまで多くなく、この記事を見ながら簡単に設定することができると思います。 Ray2を使用するには、以下の準備が必要です。 Amazon Bedrockのアクセス権 AWSアカウント (無料枠で利用可能) 適切なIAMポリシー を持つユーザー Amazon S3バケット (生成された動画を保存するために必要)   BedrockでLuma AI Ray2を有効化する いきなりですがここで注意点! マネジメントコンソールにログインしたらとりあえずBedrockにアクセスして…と言いたいところですが、まずはリージョンを オレゴンリージョン(us-west-2) に切り替えましょう! 現在 Ray2はオレゴンリージョンのみのサポート となっているのでここで変更を忘れてしまうと、せっかくモチベがあるのにアクセスできない、なんてことも…。 リージョンを変更したらAmazon Bedrockにアクセスしてサイドバーをスクロールした一番下、 「モデルアクセス」からLuma AI – Ray2を有効化 していきましょう。 Luma AIのRay2のアクセスのステータスが 「リクエスト可能」 となっていると思いますので、その文字をクリック、アクセス権をリクエストしていきます。 数分待つと、このように 「アクセスが付与されました」 と表示されます。ここまでくれば準備はOK!  タイタニックの名シーンをAIで再現! テキストプロンプトを考えてみる 今回の検証で最も大切な部分、テキストプロンプトを作成します。 試しにこんなプロンプトを作ってみました。 A young man and woman stand at the bow of a large ship. The woman has her arms outstretched and the man is holding her from behind. The ocean and sunset behind them. Cinematic, high quality. このプロンプトには、 登場人物(young man and woman) 、 場所(bow of a large ship) 、 ポーズ(arms outstretched, holding her) 、 背景(ocean and sunset) などを記載してみました。 正直に言うと、 この手の有名なシーンの再現度を上げるには裏技があるんです。 その方法はとっても簡単。文の末尾に 「inspired by Titanic」 と記載するだけです。 AIが認識できるタイトルであれば、そこに寄せるようなプロンプトを作成することで再現度を上げることが可能なんですが… 今回はせっかくなので、あえてタイタニックの名前を一切出さずに寄せてみましょう…! Amazon Bedrockで動画を生成してみよう では早速動画を作成していきましょう。 まずはBedrockのホーム画面、 プレイグラウンドから「Image/Video」を選択 します。 続いてモデルの選択画面が表示されるので、カテゴリは 「Luma AI」 、モデルは 「Ray」 を選択して適用をクリックします。 (モデル名の表示はRayとなっていますが、v2と記載があれば今回取り上げているRay2モデルです!) また、この際に生成した動画を保存するためのS3バケットを作成しますが、以下のポップアップの「確認」をクリックすれば問題ないのでこのまま進めていきましょう。 動画の保存先であるS3バケットにも課金がされるので、長期間保存する必要がなければS3バケットは削除するようにしましょう。 ここまで完了したら、いよいよプロンプトの入力画面です。 設定画面からは 動画の画面比率や解像度(通常540pまたは720p)、長さ(5秒または9秒)など を指定することができます。 では、先ほど作成したプロンプトを入力して実行をクリックします。 あとは数分待つだけ。 生成が完了すると、動画が画面上に表示され、動画がS3バケットに保存されます。 4. AIの再現度はいかに…? では、生成された動画のクオリティを確認していきましょう。 document.createElement('video'); https://blog.usize-tech.com/contents/uploads/2025/02/DC708E58D9DB1F8ED0BF309B87475B691580B466.mp4 結果:なんかちがう!! 今回の結果をまとめるとこんな感じでしょうか… 船の上で男女がいる、ということは再現できている。 ジャックとローズらしき人物は表現されているが、服装があまりにラフすぎる… 背景の夕焼けと海の表現はかなりリアル!すごい! 手を広げるってことは伝わっているけど、そういうことじゃない… 全体として、AIは「船首で男女が会いを深めるシーン」というコンセプトを認識できたものの、さすがに細部のディテールは表現できていなかったですね。 プロンプトの工夫や追加のパラメータ設定によって、より精度を上げることができそうです。   プロンプトを変えて再度挑戦! さて、ここで終わってもいいのですがどうしても悔しいので、もう一度プロンプトを変えて挑戦してみました。 作成したプロンプト version2がこちら↓ A man wraps his arms around a woman from behind as she stands at the bow with her arms outstretched. The ocean and sunset behind them. Cinematic, high quality. 改善のポイント: より詳細なプロンプトを作成 (男性が後ろから女性を抱いている、女性が選手で手を広げているなど) 先ほどよかった「Cinematic, high quality」は継続 こうして作成されたリベンジ動画がこちら! https://blog.usize-tech.com/contents/uploads/2025/02/AFF0A35CD8BEE3AF53EE36A38481F03BADF1387A.mp4 うーん、これもなんか違うかもしれないですね…笑 やはり日常的にする行動ではないこともあり、AIの学習データの中に手を広げる女性を後ろから男性が抱擁するというニュアンスが伝わりづらいのかもしれないですね…   6. まとめ 今回はAmazon BedrockのRay2を使って、映画『タイタニック』の有名なワンシーンをAIで再現してみました。 結果として、全体の雰囲気はある程度再現できましたが、細部の再現度にはまだ改善の余地がありました…。 学び プロンプトを工夫することで、自分の想像に近い映像を作ることが可能! AIの学習データの中に少ないと思われるような動作は、なかなか再現しづらい…? 生成された動画を素材として編集することで、より良い映像作品が作れるのでは…?   Ray2は簡単に動画を生成できるため、他の映画の名シーン再現や、オリジナル映像の作成にも応用可能です。 ぜひ、皆さんも試してみてください!    
アバター
SCSKの畑です。 以前のエントリ の続き・・ではないのですが、データメンテナンス機能に関する言及という観点は同じなのでその2としました。今回は、データメンテナンス機能の対象となる Redshift の特性を踏まえた上で、アプリケーションの実装において考慮する必要があったポイント及び機能について記載します。Redshift そのものというよりは、DWH の特性とある程度言い換えて良いかもしれません。   アーキテクチャ図 今回主に言及するのは Redshift のみですが、前回エントリと関連した内容を含むため一応載せておきます。   ポイント1. テーブル定義/データの更新チェック機能 以前のエントリ で説明した通り、テーブル定義/データのバージョン管理の要件があること、テーブル定義変更(=DDL操作)についてはアプリケーション外部で実行されることの2点より、アプリケーション側からテーブル定義/データの更新をチェックできる必要がありました。 具体的には、S3 上に出力・配置される対象テーブルの定義/データファイルのハッシュ値を比較することで行っています。対象テーブルの定義/データのバージョン管理を S3 を使用して行っているため、最新のバージョンの定義/データと、チェック実施時の Redshift 上の定義/データを比較して、差異があれば Redshift 側に更新があったことが分かる仕組みです。 が、実はこれは苦肉の策でした。更新チェックを実施するために実質的に Redshift 上の対象テーブル定義/データの全量を取得しているに等しく、コストが大きいためです。通常、本アプリケーション上で対象テーブルを表示する際には、以下のようなロジックを実行しています。 対象テーブルの定義/データ更新をチェック Redshift 上のテーブルが更新されている場合は、更新チェックの際に S3 上に出力したファイルを最新バージョンとして更新 最新バージョンのファイルのテーブル定義/データをアプリケーション上で表示 このようなロジックとした理由はいくつかあるのですが、アプリケーションから対象テーブルを表示する際に毎回 Redshift から全量を取得せずに更新の有無だけをチェックし、更新がない場合はそのまま S3 からテーブル定義/データを取得するようにすることで、レスポンスの向上を狙いの一つとしていました。ところが、実際の挙動としては1.による更新チェックのタイミングで Redshift から毎回全量を取得しているに等しいため、その目論見が崩れてしまっています。逆に言うと、更新チェックはもっと少ないコストで実施できると考えていました。 1.による更新チェックを任意のタイミングで実行するようなロジック・画面とするというのが回避策の一つだと思うのですが、そうするとテーブル定義/データの整合性を担保する難易度が上がってしまうこともあり、現時点ではこのようなロジックとしています。 というところでようやく Redshift (DWH) の特性に関連した話になるのですが、、通常のデータベース (RDBMS) だと、このような情報はデータベース側の管理情報として管理されているものが多いです。例えば Oracle の場合は以下 URL の通り、テーブル定義やデータの更新日時についてもデータベース側の管理情報ビューとして管理されています。(後者は統計情報取得との兼ね合いもあるので単純な管理情報とは言い難い部分もありますが・・)後は同情報をアプリケーション側でも持っておいて、突き合わせれば簡単に更新チェックができます。 https://docs.oracle.com/cd/E82638_01/refrn/ALL_OBJECTS.html https://docs.oracle.com/cd/E82638_01/refrn/ALL_TAB_MODIFICATIONS.html 対して、Redshift のような DWH の場合、通常のデータベース (RDBMS) と比較してより大量のデータを扱う目的から、このような管理情報についてはオミットされているものも多いです。DWH におけるデータの保持方式や管理方式が RDBMS と異なること、より大量データを扱う以上管理情報を RDBMS の場合と同じように扱うコストが甚大になること、そもそもの DWH の用途を鑑みると想定されていない/必要とされないと製品・サービス側で判断されていること、などの理由が考えられますが、いずれにせよ Redshift ではこのような機能がなかったため、先述したような仕組みを実装する必要があったということです。唯一、以下 URL のビューが近しい情報を含んでいましたが、さすがにテーブル作成時刻のみだとちょっとどうしようもなかったですね・・ https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/r_SVV_TABLE_INFO.html Redshift は RDBMS である PostgreSQL をベースにしていることもあり、最初は PostgreSQL 側のビューなどから取得できるのでは?と淡い希望を抱いていたのですが、結論から言うとそもそも PostgreSQL 側でもそのような情報を取得するのには一工夫必要のようでした。Oracle は(良くも悪くも)高機能・多機能な RDBMS なので、それを基準に考えることの功罪があるかもしれません・・   ポイント2. データバリデーションチェック機能 データのメンテナンス・更新にあたり大事なポイントの1つがデータの整合性を保つことです。データの整合性と一口に言っても様々な観点があるかと思いますが、最も基本的な観点としては列定義や制約(NOT NULL/PK/UK/FK)などのテーブル定義に違反したデータが更新されないかどうかが挙げられると思います。もちろん、本案件事例でも要件に含まれていました。 通常のデータベース (RDBMS) であれば、基本的にデータベース側でバリデーションチェックが行われるため、これらのテーブル定義に違反したデータは更新できないようになっています。このため、ここで言及しているようなデータ整合性を担保するだけであればアプリケーション側での考慮は不要です。 では Redshift の場合はどうかという話ですが、以下 URL の通り NOT NULL 以外の制約は制約として機能しません。定義自体はできますがあくまでもクエリ実行時に Redshift 側で効率的にデータを処理するためのプラン(実行計画)を立てるための参考情報として扱われ、データ自体の制約としては機能しません。つまり、例えば PK 制約が定義されている列に対して重複した値を INSERT することが可能といったように、これらの制約に違反するようなデータを更新することができてしまいます。 テーブルの制約 - Amazon Redshift 一意性、プライマリキー、および外部キーの制約は情報提供のみを目的としており、Amazon Redshift によって強要されることはありません。ただし、プライマリキーと外部キーはプランニング時のヒントとして使用されます。アプリケーションの ... docs.aws.amazon.com 一意性、プライマリキー、および外部キーの制約は情報提供のみを目的としており、テーブルに値を入れるときに  Amazon Redshift によって強要されるわけではありません 。例えば、依存関係のあるテーブルにデータを挿入する場合、制約に違反していても挿入は成功します。ただし、プライマリキーと外部キーはプランニング時のヒントとして使用されます。アプリケーションの ETL プロセスまたは他の何らかのプロセスによってこれらのキーの整合性が強要される場合は、これらのキーを宣言する必要があります。 もちろん(さすがに)列定義に違反するデータは更新できません。以下 URL の通り暗黙の型変換により、意図していないデータ型に変換されて更新される可能性はあるかもしれませんが、このような挙動は(製品/サービスごとの差異はあるとしても) RDBMS でも考慮されるべき内容と思います。 データ型 - Amazon Redshift Amazon Redshift によってサポートされているデータベースデータ型を使用する際に従うべき規則について説明します。 docs.aws.amazon.com よって、これらの制約に対応するデータバリデーションチェック機能をアプリケーション側で実装する必要がありました。具体的には、バリデーションチェックに失敗した場合はデータの更新を許可せず、バリデーションに失敗した(制約に違反した)データを修正するように画面上で促すようなロジックを実装することで対応しました。 また、このような機能をアプリケーション側で実装する必要があったことから、Redshift 側でチェックしてくれる列定義や一部制約についても同様にアプリケーション側でチェックするようにしました。その方がデータ更新における一連のロジック/フローをシンプルにできることが理由です。Redshift 側でチェックするということは実際に Redshift に対して更新を試行する必要があり、更に試行後のエラー内容をアプリケーション側で解釈してデータバリデーションのエラー画面を出さないといけないことにもなります。データ更新時の承認フローなどとの兼ね合いも考えると、トータルでロジックがかなり複雑になってしまうと判断しました。 なお、このような機能をゼロから実装するとさすがに工数・コスト面で厳しくなることが想定されたので、テーブルのデータ表示や編集機能を司るライブラリ探しにおいてはデータバリデーションチェック機能についても気にしました。最終的には Tabulator というライブラリを使用したのですが、詳細(もとい紹介)はまた別のエントリのネタとさせて頂こうと思います。   まとめ 業務において Oracle を中心とした RDBMS を扱っている期間が長いこともあり、Redshift(もといおおよその DWH)と RDBMS の差異としてはある程度容易に思い浮かぶような内容ではありましたが、アプリケーション実装の観点からまとめておくことも大事と考えたので今回まとめてみました。実際、ポイント1については何となくできるだろう・・みたいにタカを括っていたところできずに、最終的に今の方式に辿り着くまであれこれ試行錯誤することになったりしたので。。このへんの感覚というか勘所はもう少し意識しないといけないかなと感じました。 本記事がどなたかの役に立てば幸いです。
アバター
AWS KMSの暗号化は、S3のデフォルト暗号化などで使われることが多いと思います。 オブジェクトをPutすると自動で暗号化されるため、**「実際にどんな処理が裏で動いているのか」**を意識していない方もいるのではないでしょうか?この記事ではS3を題材にしつつ、KMS暗号化の仕組みに焦点を当てて解説します。 「KMSで暗号化するから、Encryptの権限が必要です。」 これはありがちな誤解ですが、大体の場合は間違った理解です。なぜそうなのか?その理由を紐解いていきます。 CMKはどこにいる? まずは鍵を作成しなければ始まりません。ここではカスタマーマスターキー(以下CMK)を対象鍵で作成するものとします。 キー作成はKMSのAPIである” kms:CreateKey ” が発行され、AWS管理下のどこかに対象鍵(以下CMK)が作成されます。 ここでまず頭に入れておくべきことがあります。 作成されたCMKはKMSから出てくることはありません。 このことはKMSの動きを理解する上で重要です。 作成したCMKで何らかのデータを暗号化・復号化する際は、CMKをKMSから取り出すのではなく、対象データをKMSに送って暗号化・復号化を依頼し、結果を送り返してもらう、という流れになります。 ここで次の疑問が沸いた人は鋭いです。 「でかいデータだと全部KMSに送らないといけないのでわ・・・・RDSとかEBSとかどうするの? ^^;」 実際は暗号化したいデータをKMSに送ったりはしていません。「データを暗号化する鍵」をCMKで暗号化してやりとりすることでこの問題を回避しています。 KMS(CMK)が暗号化できる対象は4096Byteまでという制限があるため、そもそもでかいデータは暗号化できないのです。 GenerateDataKey 唐突ですが、KMSには” kms:GenerateDataKey “いうActionがあります。(この話題での最重要アクションです。) CMKを引数として実行し、以下の2つの文字列を返してきます。以下はAWS CLIで実行してみたものです。 $ aws kms generate-data-key --key-id arn:aws:kms:ap-northeast-1:999999999999:key/99999999-9999-9999-9999-999999999999 --key-spec AES_256 { "CiphertextBlob": "AQIDAHiF7qVe(略)", "Plaintext": "eS7mjjJQby2(略)", "KeyId": "arn:aws:kms:ap-northeast-1:999999999999:key/99999999-9999-9999-9999-999999999999" } “Plaintext”             単なるバイト列 “CiphertextBlob”    Plaintext を指定したCMKで暗号化したバイト列 + メタデータ KMSはGenerateDataKeyを受けると、内部でランダムな文字列を生成し(Plaintext)、それを指定されたCMKで暗号化し(CiphertextBlob)、その2つを返してくれます。 この”Plaintext” のことを データキー と言い、実際のデータの暗号化の鍵として使われます。(ファイルやらEBSやらRDSやら。。) ここでは重要な点が2つあります。 まず、データキーはKMSの外側に出てきているということ。 次にデータキーを用いた暗号化(Encrypt)は、 kmsのアクションではない 、ということ。(一般的な暗号化なのかな。AES?) また、CiphertextBlob のメタデータにはCMKの情報を含んでいます。つまり 暗号化されたデータキーは、 自分がどのCMKで暗号化されているのかを知っています 。このことはデータ復号化の時に大変重要になってきますので覚えておいてください。(また今度書くかも) データ暗号化の流れ 以上の内容をまとめまして、データ暗号化の流れは以下のようになります。例としてS3にPutする場合を示していますが、例えばEBSの暗号化の流れも同じようなものになります。       ユーザはKMSに対して、作成済みのCMKを指定してkms:GenerateDataKey を発行する。 CMKはデータキーとデータキーを暗号化したものを返す。 ここでCMKの役割は終わっています。       ユーザはデータキーを使ってデータを暗号化し、そのデータキーを廃棄 この暗号化はKMSの外側で行われています。       暗号化されたデータに暗号化されたデータキーを添えて、S3に保存 (エンベロープ暗号化、とか言ったりします。)         最後で データに暗号化されたデータキーを一緒にして保存している ことは覚えておきましょう。 「鍵とデータ一緒にして大丈夫なの?家のドアに鍵を貼り付けてるようなものでは?」とは思わないように。この場合、鍵自体が暗号化された状態ですので、このままでは使えません。CMKに復号化を依頼できる人だけがこのデータを復号できます。 以上のフローを見てわかるように、KMSに対してはkms:GenerateDataKeyだけしか実行していません。なのでデータ暗号化の際に必要な権限としては kms:GenerateDataKeyがあればよい 、ということになります。(kms:Encryptではなく!)   以上。データ暗号化の時の基本的な流れを説明してみました。 若干フローなどは単純化している個所もありますが、理解の助けになれば幸いです。
アバター
SCSKの畑です。 Amplify を使用したアプリケーション開発中に発生した事象の原因及び解決策について、Web 上にあまり情報がなかったことも含めて解決に少々手こずったので共有します。引き続き今回も小ネタです。   小ネタ本題 タイトルの繰り返しになるのですが、以下のようなスキーマを定義した際、Amplify codegen により生成された query にネストされた type が含まれなかったという事象が発生しました。ちなみに本スキーマは2つの Redshift テーブルの定義及びデータを差分比較結果を格納するためのもので、AddedRowsInfo/DeletedRowsInfo/UpdatedRowsInfo に差分のあった行情報がネストされて格納されます。 ちなみに、差分比較処理自体は素直に AppSync から Lambda リゾルバを使用して実現していますが、フロントエンド側での表示も含めてそこそこ苦労した部分なので、機会があれば別エントリとして書くかもしれません。 type DataDiffInfo { diff_summary: RSS3DiffStatus! added_rows_info: [AddedRowsInfo]! deleted_rows_info: [DeletedRowsInfo]! updated_rows_info: [UpdatedRowsInfo]! } type RSS3DiffStatus{ column: Boolean constraint: Boolean data: Boolean } type PKInfo { name: String! value: String! } type AddedRowsInfo { pk: [PKInfo!]! row_data: String! } type DeletedRowsInfo { pk: [PKInfo!]! row_data: String! } type UpdatedRowsInfo { pk: [PKInfo!]! cols: [String!]! row_data: String! } で、このスキーマ定義に対して、codegen で生成された typescript の query が以下になるのですが・・ export const GetTableDataDiffInfo = /* GraphQL */ `query GetTableDataDiffInfo($input: GetTableDataDiffInfoInput!) { GetTableDataDiffInfo(input: $input) {   diff_summary {     column     constraint     data     __typename   }   added_rows_info {     row_data     __typename   }   deleted_rows_info {     row_data     __typename   }   updated_rows_info {     cols     row_data     __typename   }   __typename } } ` as GeneratedQuery< APITypes.GetTableDataDiffInfoQueryVariables, APITypes.GetTableDataDiffInfoQuery >; 見てお分かりの通り、AddedRowsInfo/DeletedRowsInfo/UpdatedRowsInfo 配下の「PKInfo」type 部分が query 定義から抜け落ちてしまっています。ネストの深さとしては一番上の階層から数えると 「3」 になりますね。   暫定回避策 さてこれは困ったということで解決策を探したのですが、探し方が悪かったのかめぼしい情報が見当たらず。最初は AppSync のクエリの深さ制限設定を疑ったのですが、デフォルト値は無制限だったためこの可能性は除外。 そこで一旦暫定的な回避策として、自分で直接 GraphQL の query を書くことにしました。codegen で 型情報を生成して欲しかったので、以下サイト様の記事通り所定のパスに query が定義されたファイルを配置しました。 AmplifyでカスタムGraphQLクエリと型情報を生成する方法 - Qiita 本記事を対象とする人Web(React,Vueなど)でAmplify利用し、自動生成されるクエリでは足りなくなった結論graphqlconfig.ymlのincludesに指定しているディレク… qiita.com ただ、当然ながら query を自分で書いている以上スキーマ定義の変更があった場合も自動で追随してくれないため、開発が続くにつれて不便さ&イライラを感じてきました。そもそも、Amplify が自動生成しないような複雑なクエリを書きたいから自分で書く必要があるのであって、今回のような事象に対しては根本的な解決策でないことは明らかであったため、本腰を入れて解決策を調べたところ・・   解決策 結論としては以下 URL の通り、.graphqlconfig.yml の maxDepth 属性で、生成する query のネストの深さを明示的に指定することで解決しました。 ただ、以下 URL に記載のある –max-depth オプションは手元の環境だと機能しませんでした。また、「max d epth」のように大文字小文字を間違えてもダメですのでご注意ください。 最初間違えてしまったのですが、エラーも出ないのでこの設定方法も機能しないのではないかと疑心暗鬼になってしまいました・・ Nested types missing from queries in generated code - Require workaround · Issue #745 · aws-amplify/amplify-cli ** Which Category is your question related to? ** iOS side generated graphql queries ** What AWS Services are you utiliz... github.com 以下、maxDepth を 5 に設定した場合の実装例です。 projects: nuxt3app:   schemaPath: src/graphql/schema.json   includes:     - src/graphql/**/*.ts   excludes:     - ./amplify/**   extensions:     amplify:       codeGenTarget: typescript       generatedFileName: src/API.ts       docsFilePath: src/graphql       maxDepth: 5 extensions: amplify:   version: 3 こちらはオプション指定して codegen した query の内容です。PKInfo の type が追加されていることが確認できます。 export const GetTableDataDiffInfo = /* GraphQL */ `query GetTableDataDiffInfo($input: GetTableDataDiffInfoInput!) { GetTableDataDiffInfo(input: $input) {   diff_summary {     column     constraint     data     __typename   }   added_rows_info {     pk {       name       value       __typename     }     row_data     __typename   }   deleted_rows_info {     pk {       name       value       __typename     }     row_data     __typename   }   updated_rows_info {     pk {       name       value       __typename     }     cols     row_data     __typename   }   __typename } } ` as GeneratedQuery< APITypes.GetTableDataDiffInfoQueryVariables, APITypes.GetTableDataDiffInfoQuery >; また、同オプションのデフォルト値は 「2」 ということで、先般のスキーマ定義において PKInfo 以下の type が出力されなかった理由も辻褄が合ってスッキリしました。正直、デフォルト値はもう少し大きくても良いと思うんですけども・・   まとめ 以前の投稿にて Amplify.Configure に与える引数の定義が不明瞭で調査に苦労した旨書いていたのですが、本件も似たような文脈の話ではないかと思います。。 余談ですが、初めて本事象が発生した時は原因究明に結構な時間を要してしまいました。というのも、Amplify のデプロイや codegen 実行時はエラーが出ておらず、AppSync 側のスキーマ定義を確認しても問題なし。Lambda リゾルバの実装に問題がある可能性も考慮して、AWS マネジメントコンソールからクエリを直接実行してみるとちゃんと PKInfo 部分の情報も取れる。でもフロントエンド側から codegen で生成されたクエリを使用すると PKInfo 部分の情報が取れない。でもエラー自体は出ていない。という感じだったので・・ 開発当初は Amplify や AppSync、GraphQL などへの理解が十分でなかったこともありますが、Web 上の情報がもう少し多かったらもっと早く解決できた!はず!ということで小ネタではありますが、本記事がどなたかの役に立てば幸いです。
アバター
「~のサービスは次のうちどれでしょうか。」 クラウドの認定試験やIPAの午前試験などでよくある形式です。 こういう選択問題はなんとなくで解けてしまうことも多いですよね。 私も試験勉強中は 「よくわからないけど、これかな~?」 と曖昧な理解で正解した時期がありました。 大量の問題演習で何とかしのいでいましたが、こんな勉強法を脱却したいと日々悶々。 そんな思いがある中、実務で触れて理解が深まった Azureの「プライベートエンドポイント」 についてまとめます。 プライベートエンドポイントとは? AzureのPaaSサービスに接続するための手段のひとつです。 仮想ネットワーク内の プライベートIPアドレス を使用して PaaSリソース に接続するために使用します。 パブリックアクセスを無効化することで、インターネット経由のアクセスを防ぐことも可能です。 つまり セキュリティ向上の利点 があるわけです。                       試験勉強中はこの概念を流し読みしていましたが、そもそも「PaaSリソースとは何か?」をきちんと理解できていませんでした。 「なんとなく、インターネットを介さずに何かにアクセスできる仕組み」といった認識だったのです。それでも試験の問題には正解できてしまうので、深く考えることなく先に進んでしまっていました。 問題を解いてみる 例えば、次のような問題があるとします。 問1 仮想ネットワークのプライベートIPアドレスを使用してPaaSサービスに接続するためのサービスはどれ? a. Azure Bastion b. プライベートエンドポイント c. Azure Load Balancer d. Azure ExpressRoute この問題では、「プライベートIPアドレス」というキーワードだけに注目して”b”のプライベートエンドポイント選んでました。なぜかPaaSサービスに接続~のくだりを読み飛ばしていたのです。これで正解してしまいます。 問2 「」の内容が 正しい 場合は”変更は必要ありません” そうでない場合は正しい回答を選べ 「パブリックエンドポイント」を使用すると、Azure Cosmos DBなどのPaaSサービスに接続するためのパブリックアクセスを無効にできる。 a. プライベートエンドポイント b. 仮想ネットワークピアリング c. Azure ExpressRoute d. 変更は必要ありません パブリックアクセスを無効とくればプライベートエンドポイントで”a”を選択してました。こちらでもAzure Cosmos DBなどの記載を無視して解いていたのです。 問3 次のリソースがある。 名前 リソース種別 説明 VNET1 仮想ネットワーク ー VM1 仮想マシン VNET1に配置 Storage1 ストレージアカウント ー VM1がプライベートIPアドレスを使用してStorage1にアクセスできるように構成するにはどれを使うべきか? a. ユーザー割り当てマネージドID b. Azure Firewall c. プライベートエンドポイント d. Application Gateway 問1と同じようにプライベートIPアドレスとくればプライベートエンドポイント”c”を選べてしまいますが、 アクセス先がストレージであることに理由があったんだなぁ と今になって気づきました。 自分が何を理解していて、何を見落としていたのかがよく分かります。理解して解けるようになると問題設定も結構おもしろいです。 PaaSサービスの具体例 振り返ってみると、問題の意図がより明確に見えてきます。 そもそもPaaSサービスって具体的に何のことでしょうか? 公式ドキュメント見ると。プライベートエンドポイントの文脈で出てくるPaaSサービスとは以下のサービスのことです。 Azure Storage Azure Cosmos DB Azure SQL データベース Private Link サービスを使用する独自のサービス プライベート エンドポイントとは – Azure Private Link | Microsoft Learn 実務でストレージにプライベートIPを付与する場面を見たことで、やっとこの概念を理解できました。 文字情報だけでは気づけないことも多いと 痛感 しました。 デモ 自分でもストレージアカウントにプライベートIPアドレス付与してみようと思います。 1. ストレージアカウントの左ペインからセキュリティとネットワークを開き、ネットワークを選択。 プライベートエンドポイント接続、+プライベートエンドポイントを押下します。                     2.基本タブ入力。 名前を入力するとネットワークインターフェイス名が自動で作成された。               3.リソースタブでは対象サブリソースで、ストレージの種類選択。今回はblobになります。                 4. 仮想ネットワークタブではプライベートエンドポイントを作成するサブネットを指定。 このサブネット上にプライベートエンドポイント作成されプライベートIPアドレスが構成されます。                     5. DNSタブではプライベートDNSゾーンと統合するではいを選択。DNSレコードが自動で構成されます。             6.確認。 プライベートIPアドレス 10.0.156.4 が付与されました。                                                   7.プライベート経由のアクセス許可の確認 プライベートエンドポイントと同じ仮想ネットワーク上のVMへリモートデスクトップ接続してnslookup コマンド実施。 以下のようにプライベートIPアドレスが応答される。         自分のPCからnslookup実行するとパブリックIPアドレスが応答され、ストレージにアクセスできない。           さいごに 3月にAZ-305(Microsoft Certified: Azure Solutions Architect Expert)を受験します。 AZ-104よりも要件が複雑になっているので、理解しながら解けるようになろうと思います。 ふんわりした資格勉強から卒業し、実務で活かせる知識を身につけるために、しっかりとした学習を進めていきます。
アバター
こんにちは!SCSKの新人営業、栗山です。 皆さんの会社では、電話応対をどのように行っていますか? 顧客対応の質向上や効率化 は、多くの企業にとって重要な課題ですよね 近年、AI技術を活用した 電話応対のDX が注目されています。 例えば、音声認識技術を使えば、顧客との会話を自動でテキスト化し、分析したり、対応を効率化したりすることが可能になります! 今回は、Google Cloudが提供する音声認識サービス Google Cloud Speech-to-Text の検証を通して、AIによる電話応対DXの可能性を探ってみました! Google Cloud Speech-to-Tex(以降Speech-to-Text)は、高精度な音声認識を簡単に実現できるサービスです。 本記事では、Speech-to-Textを実際に使ってみた感想や検証結果を共有することで、 AI技術による電話応対DXに興味がある方 Speech-to-Textの導入を検討している方 文字起こしツールを活用したいけど何にしようか悩んでいる方 音声データを分析して業務に役立てたいと考えている方 にとって、少しでも役立つ情報になれば幸いです! 検証目的 コンタクトセンター業界 のお客様からは、音声データの文字起こしに対して、有用なサービスは無いかと質問を受けるケースが良くあります。 あるお客様は現状、オペレーターの対応時の録音データを分析に活用するため、 何度も聞き直しながら手作業で文字起こし を行っており、非常に時間と手間がかかっているとのことでした。。。 もし、この 文字起こし作業をAIで効率化 できれば、担当者はより創造的な業務に集中できます。 例えば、顧客対応の傾向分析や、サービス品質向上のための施策検討などに時間を有効活用できるでしょう。 そこで今回、限りなく実際の応対に近いテスト音声データを使い、Speech-to-Textによる音声認識精度の簡易検証を実施することで、 Speech-to-Textの導入により、お客様の文字起こし作業の効率化と負担軽減に貢献できる可能性 を明らかにしました!   なぜGoogle Cloud Speech-to-Textを選んだのか 導入の容易さ:  GUIが用意されており、初期設定が簡単で、すぐに検証を開始できる! コストパフォーマンス: 無料枠60分があり、コストを気にせず試しやすい! 高精度のリアルタイム文字起こし: 他クラウドと比較しても遜色ない性能! 他クラウドとの比較(文字起こしサービス編)       Google  Cloud      Speech-to-Text Amazon Transcribe    Microsoft Azure    Speech to Text AmiVoice Cloud Platform(Amivoice API) 対応言語 日本語を含む125以上の言語 日本語を含む複数言語 日本語を含む多数の言語 日本語、英語、中国語、韓国語 料金 約0.046円/秒 ※60分無料枠あり ※新規利用者は$300相当のクレジット ※ログ許可で割引あり 約0.046円/秒 ※利用量割引あり 約0.046円/秒 ※1か月あたり5音声時間は無料 0.044円/秒 ※毎月60分無料枠あり ※ログ許可で割引あり GUIでの利用 〇 〇 〇 × ※単語登録のみ可能 他サービスとの連携 〇 他Google Cloudサービスと容易に連携 〇 他AWSサービスと容易に連携 〇 他Azureサービスと容易に連携 〇 リアルタイム性 低遅延で字幕表示も可能 リアルタイム対応可能だが速度に制限あり 雑音環境での処理に強いが速度は平均的 リアルタイム性は他社と比較して平均 導入の容易さ デフォルトモデルで高精度・即利用可 即時利用可能 高精度だがカスタマイズ設定が必要 APIを利用したプログラミングが必要 あなたのユースケースに最適な音声文字起こしサービスはどれ?主要3社を比較してみた | ネットワンシステムズ ※あくまで公開されている情報や個人の見解に基づいており、モデルや設定によって結果が異なる場合があることにご注意ください。 Speech-to-Textで 期待できること Speech-to-Textは、音声データをリアルタイムまたはバッチ処理で文字起こしする機能を提供します。Speech-to-Textを活用・組み合わせて以下のような期待が持てます。 会議録音の文字起こしでの作業効率化 コールセンターでの問い合わせ分析 動画コンテンツの字幕生成               etc..   検証プロセス ① データ準備 検証に使用するデータは以下の2つです。 音声データ( MP3, FLAC, AMR, LINEAR16 など) 正解データ 音声データから一言一句書き起こしたテキストデータ(手動で作成) 評価を正確に行うため、改行やスペース、句読点(「、」「。」)も含まれていない ② 音声ファイル読み込み 今回はMP3の音声ファイルを読み込んでいます。(Cloud Storageのファイルも利用可能) チャンネルごとに別個の認識: 有効 音声データをアップロードすると自動的にサンプリングレートを割り当てくれます! ③ 音声文字変換のオプション APIバージョン:V1 使用する言語:Japanese 文字起こしモデル:Telephony リージョン:global 文字起こしモデル とは、音声データをテキストデータに変換するAIモデルのことです。Speech-to-Textでは、様々な種類の音声データに対応するために、複数のモデルが用意されています。 今回の検証では、通話録音データに最適化された Telephonyモデル を使用しました。Telephonyモデルは、電話会話特有のノイズや音声品質の変動に強く、通話内容の文字起こしに高い精度を発揮します。 その他モデルについては以下をご参照ください! 音声文字変換モデルを選択する  |  Cloud Speech-to-Text V2 documentation  |  Google Cloud cloud.google.com 詳細設定: 今回は全て無効にしましたが、下記の高度な詳細設定が可能です。 冒とく的な語句フィルタ 句読点入力の自動化 発話された句読点 発話された絵文字 話者ダイアライゼーション 単語の時間オフセット ※2024年12月時点 一部日本語対応していない機能ございます。 今回 カスタム音声モデル の適用はしませんでした。固有名詞や専門用語に対応する場合は、モデルを作成することで、認識精度をさらに向上させることが可能です。 ④ 正解データインポート 文字起こし精度を正しく評価するために、正解データ(音声データの内容を正確に書き起こしたテキストデータ)をインポートします。 今回は、自ら音声ファイルを手打ちで文字起こした正解データを用意しました。この正解データは、文字ベースでの認識制度を図るため、句読点や改行など、実際に話されていない文字は含めていません。 この正解データをSpeech-to-Textにインポートすることで、音声認識結果と正解データを比較し、認識精度を自動で算出することができます。   検証結果 成果 認識精度:約90%以上 文字レベルでの一致率を測定した結果です! 高い精度で文字起こしが可能であることが確認できました! 処理速度:音声データ1分あたり約60秒で処理 (同時実行可能) 非常に高速な処理を実現! 複数ファイル同時実行可能で、手作業に比べて大幅な時間短縮が可能! 観察事項 固有名詞誤認識が一部確認 一部音声ファイルの品質(背景ノイズや録音距離)に依存 今回の検証では、Speech-to-Textが 高い認識精度と処理速度 を持つことが確認できました。実際に私が1分あたりの音声データを一言一句文字起こしすると5分かかりましたので、 約80% の時間削減 が見込まれることになります (※1) 。これにより実際の担当者はより戦略的な業務に時間を活用できます。 今後は、削減された時間で、BigQueryなどのデータ分析基盤と連携し、文字起こしデータを様々な角度から分析することで、顧客対応の質向上や新たなビジネスチャンスの発掘が期待できます! ※1 あくまで一例であり、音声ファイルの品質や内容、オペレーターの習熟度などによって削減時間は変動します。 さらに精度を上げるには? カスタム音声モデルの作成 固有名詞や専門用語を学習させることで、精度を向上させます! 音声品質の改善 マイクの見直しやノイズ環境の調整により、音声データの品質を高め、音声認識の精度を改善します! APIバージョンのアップグレード(V1→V2) 最新バージョン(V2)を使用することで、性能の向上が期待されます!   なぜSCSK? SCSKは、Google Cloudのプレミアパートナーとして、お客様の課題解決に最適なクラウドサービスを選定し、導入から運用までをトータルでサポートします。お客様に寄り添い、長年の経験で培った技術力で、ビジネスの成長を力強く後押しします。 1. 幅広いクラウド技術の知見 Google Cloudはもちろん、AWS、Azureなど、マルチクラウドに対応したエンジニアが多数在籍しています。お客様のニーズやビジネスの特性に合わせて、最適なクラウド環境を構築し、柔軟なシステム基盤を提供いたします。 さらに、SCSK独自のプライベートクラウドサービス「USiZE」も提供しており、パブリッククラウドと組み合わせたハイブリッドクラウド環境の構築も可能です。 2.トータルサポート体制 40年以上にわたるシステム構築・運用実績で培った業界知識と、クラウドに関する高い技術力、そして 2,500名以上の認定技術者 を擁するSCSKだからこそ、お客様のビジネスに最適なクラウド環境を実現できます。 お客様の業界基準やコンプライアンスに準拠した、強固なセキュリティ体制を構築し、ISO 27001認証取得のデータセンターで運用することで、お客様のデータ資産を安全に保護します。 また、お客様のクラウド活用を支援する、幅広いサービスラインナップを取り揃えています。 クラウドサービス 時代の急激な変化に素早く柔軟に対応。キーワード「クラウドサービス」に関する製品・サービス一覧をご覧いただけます。 www.scsk.jp 3. AIの導入実績 AI技術を活用したシステムの導入実績も豊富です。AIチャットボット、需要予測AI、画像認識AIなど、様々な分野で実績があります。お客様のビジネス課題を解決に導く、最適なAIソリューションを提案します。 So-net 様 AI本番導入事例 : コンタクトセンターにてチャットボット、ボイスボットを導入し、オペレーターなしで回答を自動化。オペレーター応対件数を 35%削減 を実現 AI本番システム実装事例集|ダウンロード|クラウド移行だけでは描けない、理想のDXを実現する www.scsk.jp   おわりに いかがでしょうか。今回の検証では、Speech-to-Textが文字起こし作業の大幅な効率化に貢献できることが示されました。特に、 処理速度と認識精度は期待以上 であり、実務での活用に十分耐えうるレベルであると言えます。 Speech-to-Textの導入は、シンプルなUIで、配属1か月の営業担当の私でも たった2日 で使いこなすことができました。ただ、本格的な文字起こし作業を完了するには、APIやSDKを利用したプログラミングが必要になる場合があります。 今後も積極的に技術に触れ、お客様の課題に最適な提案ができる営業を目指します。 本記事をご覧いただき、詳細をご希望の方はお気軽にお問い合わせください!       ※本記事の内容は執筆者個人の見解であり、所属する組織の見解を代表するものではありません。
アバター
はじめに 検証でAzure環境とAWS環境をVPN接続した環境が必要となり、以下記事を参考に環境を構築しようとしました。 最低限のコストで、必要な時に作ったり消したりを気軽にできるよう、テンプレート化してみたという記事です。 チュートリアル - ポータルを使用して Azure と アマゾン ウェブ サービス (AWS) 間の BGP 対応接続を構成する - Azure VPN Gateway このチュートリアルでは、アクティブ/アクティブ VPN Gateway と AWS 上の 2 つのサイト間接続を使用して Azure と AWS を接続する方法について説明します。 learn.microsoft.com 上記記事の完全体はアクティブ-アクティブ構成かつ2つのトンネルで構成されていますが、今回はアクティブ-アクティブを無効にしてトンネルを1つだけ構成してます。段階的には成長期です。 一時的な検証用途なので、最低限の構成でつながればいいやという思想です。イメージはこんな感じ。 概要図 図としては、以下のような感じです。 テンプレート テンプレートは3つ用意しています。これはリソース構築後に払い出される値が必要なリソースがあるためです。 例えば、AWS側のカスタマーゲートウェイにAzureのパブリックIPが必要である、とか。 作成の大まかな流れは以下の通りです。 Step 作業項目 備考 Step1:【Azure】NW基盤作成 ①VNet・サブネットの作成 ②Virtual Network Gateway用パブリックIPの作成 対応テンプレート: azure_network_resource.json Step2:【AWS】VPNリソース作成 ①VPC作成 ②カスタマーゲートウェイ作成 ③仮想ネットワークゲートウェイ作成 ④VPN接続作成 ⑤ルート伝搬の有効化 対応テンプレート:aws_vpn_resource.yaml Step3:【Azure】VPNリソース作成 ①Local Network Gateway作成 ②Virtual Network Gateway作成 ③VPN接続作成 対応テンプレート:azure_vpn_resource.json Step1 :【Azure】NW基盤作成 指定しているパラメータ パラメータ名 デフォルト値 備考 vnetName VNet1 作成するVNetの名前 vnetAddressPrefix 10.1.0.0/16 作成するVNetのCIDR範囲 subnet1Prefix 10.1.0.0/24 GatewaySubnetのCIDR範囲 vpnpipName VNet1GWpip パブリックIPの名前 コード ファイル名:azure_network_resource.json {   "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",   "contentVersion": "1.0.0.0",   "metadata": {     "_generator": {       "name": "bicep",       "version": "0.6.18.56646",       "templateHash": "10806234693722113459"     }   },   "parameters": {     "vnetName": {       "type": "string",       "metadata": {           "description": "VNet Name"         },       "defaultValue": "VNet1"     },     "vnetAddressPrefix": {       "type": "string",       "metadata": {           "description": "VNet CIDR range"         },       "defaultValue": "10.1.0.0/16"     },     "subnet1Prefix": {       "type": "string",       "metadata": {           "description": "Gateway Subnet CIDR range"         },       "defaultValue": "10.1.0.0/24"     },      "vpnpipName": {       "type": "string",       "metadata": {           "description": "Public IP Name"         },       "defaultValue": "VNet1GWpip"     }   },   "resources": [     {       "type": "Microsoft.Network/virtualNetworks",       "apiVersion": "2024-05-01",       "name": "[parameters('vnetName')]",       "location": "[resourceGroup().location]",       "properties": {         "addressSpace": {           "addressPrefixes": [             "[parameters('vnetAddressPrefix')]"           ]         },         "subnets": [           {             "name": "GatewaySubnet",             "properties": {               "addressPrefix": "[parameters('subnet1Prefix')]"             }           }         ]       }     },     {       "type": "Microsoft.Network/publicIPAddresses",       "apiVersion": "2024-05-01",       "name": "[parameters('vpnpipName')]",       "location": "[resourceGroup().location]",       "sku": {         "name": "Standard",         "tier": "Regional"       },       "properties": {         "publicIPAllocationMethod": "Static",         "idleTimeoutInMinutes": 4       }     }   ]   } Step2:【AWS】VPNリソース作成 指定しているパラメータ パラメータ名 デフォルト値 備考 myVPCName VPC1 作成するVPCの名前 myVPCCIDR 10.2.0.0/16 作成するVPCのCIDR範囲 VGWName AzureGW 仮想ネットワークゲートウェイの名前 CGWName ToAzureInstance0 カスタマーゲートウェイの名前 VPNConnectionName ToAzureConnection VPN接続の名前 CustomBGPASN 65000 Azure側GatewayのASN azurepip なし Step1で作成したパブリックIPを指定 コード ファイル名:aws_vpn_resource.yaml AWSTemplateFormatVersion: '2010-09-09' Description: Create a Virtual Private Gateway and Customer Gateway Parameters: myVPCName:   Type: String   Default: "VPC1" # VPCの名前 myVPCCIDR:   Type: String   Default: "10.2.0.0/16" # VPCのCIDR範囲 VGWName:   Type: String   Default: "AzureGW" # 仮想ネットワークゲートウェイのリソース名 CGWName:   Type: String   Default: "ToAzureInstance0" # カスタムネットワークゲートウェイのリソース名 VPNConnectionName:   Type: String   Default: "ToAzureConnection" # VPN接続の名前 CustomBGPASN:   Type: Number   Default: 65000 # 任意のASNを入力 azurepip: # スタック作成時にAzure側のパブリックIPを入力する。     Type: String Resources: # VPCの作成 myVPC:   Type: AWS::EC2::VPC   Properties:     CidrBlock: !Ref myVPCCIDR     Tags:       - Key: Name         Value: !Ref myVPCName MyVpcDefaultRouteTable:   Type: AWS::EC2::RouteTable   Properties:     VpcId: !Ref myVPC # 仮想プライベートゲートウェイの作成 VirtualPrivateGateway:   Type: AWS::EC2::VPNGateway   Properties:     Type: ipsec.1     Tags:       - Key: Name           Value: !Ref VGWName   # 仮想プライベートゲートウェイをVPCにアタッチ VPCGatewayAttachment:   Type: AWS::EC2::VPCGatewayAttachment   Properties:     VpcId: !Ref myVPC       VpnGatewayId: !Ref VirtualPrivateGateway # カスタマーゲートウェイの作成 CustomerGateway:   Type: AWS::EC2::CustomerGateway   Properties:     BgpAsn: !Ref CustomBGPASN     IpAddress: !Ref azurepip  # カスタマーゲートウェイのパブリックIPアドレス     Type: ipsec.1     Tags:       - Key: Name         Value: !Ref CGWName   # VPN接続の作成 VPNConnection:   Type: AWS::EC2::VPNConnection   Properties:     Type: ipsec.1     CustomerGatewayId: !Ref CustomerGateway     VpnGatewayId: !Ref VirtualPrivateGateway     StaticRoutesOnly: false  # 動的ルーティングとする。     Tags:       - Key: Name         Value: !Ref VPNConnectionName     VpnTunnelOptionsSpecifications:       - TunnelInsideCidr: "169.254.21.0/30"  # トンネル1の内部IPv4 CIDR         - TunnelInsideCidr: "169.254.22.0/30"  # トンネル2の内部IPv4 CIDR   # ルート伝搬の有効化 EnableRoutePropagation:   Type: AWS::EC2::VPNGatewayRoutePropagation   Properties:     RouteTableIds:       - !Ref MyVpcDefaultRouteTable     VpnGatewayId: !Ref VirtualPrivateGateway     DependsOn: VPCGatewayAttachment Outputs: VirtualPrivateGatewayId:   Description: "The ID of the Virtual Private Gateway"   Value: !Ref VirtualPrivateGateway CustomerGatewayId:   Description: "The ID of the Customer Gateway"     Value: !Ref CustomerGateway VPNConnectionId:   Description: "The ID of the VPN Connection"     Value: !Ref VPNConnection Step3:【Azure】VPNリソース作成 指定しているパラメータ パラメータ名 デフォルト値 備考 myVNet VNet1 Step1で作成したVNetの名前 publicIpName VNet1GWpip Step1で作成したパブリックIPの名前 localNetworkGatewayName lngw_test Local Network Gatewayの名前 asn 64512 AWS側のASN bgpPeeringAddress 169.254.21.1 Local Network GatewayのピアIP customBgpIpAddress 169.254.21.2 Virtual Network GatewayのピアIP virtualNetworkGatewayName vngw_test Virtual Network Gatewayの名前 vngwasn 65000 Azure側のASN gatewaySku VpnGw1 VPN GatewayのSKUを指定 virtualNetworkConnectionName AWSTunnel1toAzureInstance0 VPN接続の名前 gatewayIpAddress なし Step2で作成したVPN接続(トンネル1)のパブリックIPを指定 PreSharedKey なし Step2で作成したVPN接続の事前共有鍵を指定 コード ファイル名:aws_vpn_resource.yaml {   "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",   "contentVersion": "1.0.0.0",   "parameters": {     "myVNet": {       "type": "string",       "metadata": {         "description": "VNet Name"       },       "defaultValue": "VNet1"     },     "publicIpName": {       "type": "string",       "metadata": {         "description": "PublicIPAddress Name"       },       "defaultValue": "VNet1GWpip"     },     "localNetworkGatewayName": {       "type": "string",       "metadata": {         "description": "LocalNetworkGateway Name"       },       "defaultValue": "lngw_test"     },     "asn": {       "type": "int",       "metadata": {         "description": "Autonomous System Number (ASN) for BGP"       },       "defaultValue": 64512     },     "bgpPeeringAddress": {       "type": "string",       "metadata": {         "description": "BGP peering address for LocalNetworkGateway"       },       "defaultValue": "169.254.21.1"     },     "customBgpIpAddress": {       "type": "string",       "metadata": {         "description": "BGP peering address for VirtualNetworkGateway"       },       "defaultValue": "169.254.21.2"     },     "virtualNetworkGatewayName": {       "type": "string",       "metadata": {         "description": "Name of the virtual network gateway"       },       "defaultValue": "vngw_test"     },     "vngwasn": {       "type": "int",       "metadata": {         "description": "Autonomous System Number (ASN) for BGP"       },       "defaultValue": 65000     },         "gatewaySku": {       "type": "string",       "metadata": {         "description": "SKU for the virtual network gateway"       },       "defaultValue": "VpnGw1",       "allowedValues": [         "Basic",         "VpnGw1",         "VpnGw2",         "VpnGw3",         "VpnGw4",         "VpnGw5"       ]     },     "virtualNetworkConnectionName": {       "type": "string",       "metadata": {         "description": "Name of the VPN Connection"       },       "defaultValue": "AWSTunnel1toAzureInstance0"     },     "gatewayIpAddress": {       "type": "string",       "metadata": {           "description": "AWS Public IP Address"         }     },     "PreSharedKey": {       "type": "string",       "metadata": {         "description": "Pre-SharedKey"       }     }   },   "resources": [     {       "type": "Microsoft.Network/localNetworkGateways",       "apiVersion": "2024-05-01",       "name": "[parameters('localNetworkGatewayName')]",       "location": "[resourceGroup().location]",       "properties": {         "gatewayIpAddress": "[parameters('gatewayIpAddress')]",         "bgpSettings": {           "asn": "[parameters('asn')]",           "bgpPeeringAddress": "[parameters('bgpPeeringAddress')]"         }       }     },     {       "type": "Microsoft.Network/virtualNetworkGateways",       "apiVersion": "2024-05-01",       "name": "[parameters('virtualNetworkGatewayName')]",       "location": "[resourceGroup().location]",       "properties": {         "ipConfigurations": [           {             "name": "vnetGatewayConfig",             "properties": {               "privateIPAllocationMethod": "Dynamic",               "subnet": {                 "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('myVNet'), 'GatewaySubnet')]"               },               "publicIPAddress": {                 "id": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIpName'))]"               }             }           }         ],         "gatewayType": "Vpn",         "vpnType": "RouteBased",         "enableBgp": true,         "activeActive": false,         "sku": {           "name": "[parameters('gatewaySku')]",           "tier": "[parameters('gatewaySku')]"         },         "bgpSettings": {           "asn": "[parameters('vngwasn')]",           "bgpPeeringAddresses": [             {               "ipconfigurationId": "[resourceId('Microsoft.Network/virtualNetworkGateways/ipConfigurations', parameters('virtualNetworkGatewayName'), 'vnetGatewayConfig')]",               "customBgpIpAddresses": [ "[parameters('customBgpIpAddress')]" ]             }           ]         }       }     },     {       "type": "Microsoft.Network/connections",       "apiVersion": "2024-05-01",       "name": "[parameters('virtualNetworkConnectionName')]",       "location": "[resourceGroup().location]",       "dependsOn": [         "[resourceId('Microsoft.Network/virtualNetworkGateways', parameters('virtualNetworkGatewayName'))]",         "[resourceId('Microsoft.Network/localNetworkGateways', parameters('localNetworkGatewayName'))]"       ],       "properties": {         "virtualNetworkGateway1": {           "id": "[resourceId('Microsoft.Network/virtualNetworkGateways', parameters('virtualNetworkGatewayName'))]"         },         "localNetworkGateway2": {           "id": "[resourceId('Microsoft.Network/localNetworkGateways', parameters('localNetworkGatewayName'))]"         },         "connectionType": "IPsec",         "sharedKey": "[parameters('PreSharedKey')]",         "enableBgp": true       }     }   ],   "outputs": {     "localNetworkGatewayId": {       "type": "string",       "value": "[resourceId('Microsoft.Network/localNetworkGateways', parameters('localNetworkGatewayName'))]"     },     "VirtualNetworkGatewayId": {       "type": "string",       "value": "[resourceId('Microsoft.Network/localNetworkGateways', parameters('localNetworkGatewayName'))]"     }   }   } 手順 ここからは上記テンプレートを用いた簡単な構築手順を記載します。なお、細かい画面遷移等は手順を省いていますのでご了承ください。 なお、Azure CLIがインストールされていることが前提となります。インストール手順は以下参照です。 Azure CLI をインストールする方法 Azure CLI は、Windows、macOS、および Linux 環境にインストールできます。 Docker コンテナーおよび Azure Cloud Shell でも実行できます。 learn.microsoft.com リソース構築手順 ①Azure CLIを使うため以下コマンドでAzureにログインします。 az login ②Azure側にリソースグループがない場合は以下コマンドでリソースグループを作成して下さい。 az group create --name <リソースグループ名> --location japaneast ③以下コマンドでAzureリソース(NW関連)をデプロイします。 az deployment group create --resource-group <リソースグループ名> --template-file azure_network_resource.json  デプロイ後、作成したパブリックIPのアドレスを控えます。 ④AWSコンソール画面のCloudFormationよりスタックを作成してください。   テンプレートファイルを読み込ませます。   パラメータとして③で確認したAzure側のパブリックIPアドレスを入力します。   その他はデフォ設定のままスタックを送信すればOKです。 ⑤CloudFormationが正常終了したら、VPN接続画面でトンネルのパブリックIPを確認します。 ⑥また、構成ファイルをダウンロードします。 ダウンロードしたファイル内に事前共有鍵が書かれてるので、後ほど使います。 ⑦最後に以下コマンドでAzureリソース(VPN関連)をデプロイします。 gatewayIpAddressで⑤で確認したパブリックIPを、PreSharedKeyで⑥で確認した事前共有鍵を指定します。 az deployment group create --resource-group <リソースグループ名> --template-file azure_vpn_resource.json --parameters gatewayIpAddress=<⑤で確認したパブリックIP> PreSharedKey=<⑥で確認した事前共有鍵> ➇以下のようになってれば、つながってるはずです。 ※Azure上で仮想VM、AWS上でEC2をたて、疎通できることを確認しました。 【Azure側】 【AWS側】 リソース削除手順 【Azure】 リソースグループを削除することで作成したリソースが全部消えます。以下コマンドを実行ください。 az group delete --name <リソースグループ名> 【AWS】 CloudFormationのスタックを削除することで作成したリソースが全部消えます。   おわりに 以上、AWSとAzureをVPN接続してみた、でした。本当に接続するとこだけしか作ってませんが。。 ちなみに構築全体流すので大体40分くらいかかります。※AzureのVPNリソース作成が30分超かかる。 コンセプトとしてはAzure、AWSに何もない状態で0から作るってことと手数をできるだけ少なくってことを意識しました。 とはいえ、AzureとAWSという異なるプラットフォームから値を引っ張ってくる必要があるので1つのテンプレートにおさめるのは難しく、手順も何ステップかに分かれてるのでもう少し工夫できないかなあと思っているところです。 余裕がでてくればそのうち冒頭のMicrosoft記事の完全体を作れるように…したいところです。
アバター
SCSK 岩井です。 前回はRaspberry Pi × 2台でWebサーバの冗長化を行いつつ、LED点灯を行いました。 今回はWebサーバの冗長化を踏襲しつつ、気温/気圧/湿度センサーを使って情報取得部分の冗長化をしてみたいと思います。   Raspberry PiでWebサーバ(冗長構成)を構築 Raspberry Piを2台使ってWebサーバの冗長化を行ってみたいと思います。 blog.usize-tech.com 2025.02.05   下準備 使用するRaspberry Piは前回同様に以下のものです。 【Raspberry Pi 5】 CPU: Broadcom BCM2712 quad-core Arm Cortex A76 processor @ 2.4GHz Memory: 8GB OS: Bookworm 【Raspberry Pi 3 Model B+】 CPU: Broadcom BCM2837B0, Cortex-A53 (ARMv8) 64-bit SoC @ 1.4GHz Memory: 1GB OS: Bookworm この2台にflaskを利用してWeb画面に測定結果を表示する構成を組んでみます。 【追加で用意するもの】 温湿度・気圧センサーモジュールキット(BME280使用) × 2 ジャンパーケーブル×8 ブレッドボード×1 Webサーバアクセス用PC   I2Cの有効化 Raspberry Piとセンサーの通信を行うために、Raspberry Pi側でI2C通信を有効化する必要があります。 コンソールで以下のコマンドを実行します。 ※以下はRaspberry Pi 5のものですが、Raspberry Pi 3も同様に設定します。 sudo raspi-config GUIが立ち上がるので、「3. Interface Options」を選択して[ENTER]キーを押します。 次の画面で「I5 I2C」を選択して[ENTER]キーを押します。 次に確認画面が表示されるので<はい>を選択し、[ENTER]キーを押します。 I2Cが有効化されたメッセージが表示されるので[ENTER]キーを押します。 Raspberry Piを再起動します。   ライブラリのインストール Raspberry PiでBME280センサーからデータを取得するために、前回分に smbus2 および bme280 ライブラリを追加します。 今回はGPIOまわりのライブラリは使用しないため、バージョン差異はありません。 Raspberry Pi 3/5共通で必要になるライブラリになります。また、I2C動作確認のためi2c-toolsライブラリも追加します。 sudo pip3 install smbus2 –break-system-packages sudo pip3 install bme280 –break-system-packages sudo sudo apt-get install i2c-tools sudo pip3 install RPi.bme280 –break-system-packages インストールオプションに「–break-system-packages」をつけないとインストール時にエラーになります。 OSがbookwormとなり、pipの扱いが厳しくなったことが原因のようです。 仮想環境を使用することが推奨されているようですが、今回は「–break-system-packages」で対処します。 また、「bme280」をインストールしているにもかかわらず、スクリプト実行時にライブラリが 見つからないというエラーが発生したため、「RPi.bme280」も併せてインストールしています。   温湿度・気圧センサーモジュールキットとRaspberry Piを接続する ブレッドボードに温湿度・気圧センサーモジュールキットを接続します。 今回もRaspberry Pi 5用とRaspberry Pi 3用に2セット回路を作ります。     次に回路とRaspberry Pi 5、Raspberry Pi 3を接続します。 センサ側 Raspberry Pi 3/5共通 BME280 VDD 3.3V:1ピン BME280 GND GND:9ピン BME280 SDI GPIO2(SDA):3ピン BME280 SCK GPIO3(SDL):5ピン 【Raspberry Pi 5のピン配置】 Raspberry Pi 5 Pinouts including GPIO for the 40 Pin Header – element14 Community 【Raspberry Pi 3のピン配置】 Raspberry Pi 3 Model B GPIO 40 Pin Block Pinout – element14 Community 接続が終わったら、以下のコマンドを実行します。 sudo i2cdetect -y 1 実行結果に「76」という表記があれば、正常に接続できています。   Pythonスクリプトの作成 前回同様にPythonでFlaskアプリケーションをRaspberry Pi 3/5でそれぞれ作成しますが、 内容は同じものとなります。画面に表示される「BME280 センサーデータ」の部分に Raspberry Pi 5は(Unit 1)、 Raspberry Pi 3は(Unit 2)と追記します。 ファイル名はtemp.pyにしてみました。  from flask import Flask, render_template_string  import smbus2  import bme280    app = Flask(__name__)  def read_bme280_data ():   port = 1 address = 0x76   bus = smbus2.SMBus(port)   bme280.load_calibration_params(bus, address)   data = bme280.sample(bus, address)     return {   'temperature' : round (data.temperature, 1 ),   'pressure' : round (data.pressure, 1 ),   'humidity' : round (data.humidity, 1 )   }    @app.route( '/' )  def index (): sensor_data = read_bme280_data()   html = '''   <!DOCTYPE html>   <html lang="ja">   <head>   <meta charset="UTF-8">   <title>センサーデータ</title>   </head>   <body>   <h1>BME280 センサーデータ</h1>   <ul>   <li>温度: {{ data.temperature }} °C</li>   <li>気圧: {{ data.pressure }} hPa</li>   <li>湿度: {{ data.humidity }} %</li>   </ul>   </body>   </html>   '''   return render_template_string(html, data=sensor_data)   if __name__ == '__main__' :   app.run(host= '0.0.0.0' , port= 5000 )   Webサーバの起動(Pythonスクリプトの実行) 各Raspberry Piのコンソールで、Webサーバを起動します。 まずはIPアドレス確認から。  # Raspberry Pi 5/Raspberry Pi 3共通  ip addr 次に各Raspberry PiでWebサーバを起動します。  # Raspberry Pi 5/Raspberry Pi 3共通  python3 temp.py   Webブラウザからアクセス Webサイトアクセス用PCでブラウザを2つ起動し、それぞれ以下のURLにアクセスします。 それぞれセンサーが稼働し、「温度」「気圧」「湿度」が表示されます。 http://Raspberry Pi 5のIPアドレス:5000 http://Raspberry Pi 3のIPアドレス:5000 湿度低め…。   冗長化確認 前回のnginxとkeepallived設定がそのまま残っているので、流用しました。 Webサイトアクセス用PC上のブラウザで仮想IPアドレスのURLにアクセスします。 http://192.168.11.110/ Unit 1の表記があり、Master側(Raspberry Pi 5)のWebサイトにアクセスしていることがわかります。 Raspberry Pi 5をシャットダウンします。 その後上記URLにアクセスするとUnit 2の表記があり、Backup側(Rapberry Pi 3)のWebサイトにアクセスしています。 センサーを稼働させながらシステムの冗長化を実現することができました。 これで片系のRaspberry Piに障害が発生しても測定を継続させることができるようになりました。
アバター
ServiceNowの生成AI機能であるNow Assist for IT Service Management(ITSM)を調べたので、学んだ内容を記事にします。 本記事は執筆時点(2025年2月)の情報です。最新の情報は製品ドキュメントを参考にしてください。   はじめに Now Assistは2023年に登場して以降、ITSMやCSM、FSM、HRSDなどなど、その対応領域はどんどん拡大されています。 今回はその中でも、ITSMの領域におけるNow Assistの機能について調べました。 仮想エージェント/ライブエージェントのチャットにおけるNow Assistの利用 仮想エージェント(Virtual Agent) ユーザーの質問や課題、要求に自動で応答し、24時間利用可能なセルフサービスを提供するチャットボット機能です。 ライブエージェント(Live Agent) ユーザーの課題が複雑で仮想エージェントによる解決ができなかった場合、ライブエージェントに接続することでオペレーター(エージェント)とチャット上で直接会話することができます。 チャット要約(Chat summarization) ユーザーが仮想エージェント、またはライブエージェントとチャット上で会話していた内容を要約する機能です。 ライブエージェントとしてユーザーからの問い合わせ対応をするオペレーターには以下のメリットがあると感じました。 ユーザーと仮想エージェント間のチャット要約を確認することで、ユーザーの問い合わせ内容・要件を素早く把握することができる ライブエージェントが異なるオペレーターにエスカレーションされた際、ユーザーと前担当者間でのやり取りを素早く把握し、スムーズに引継ぎを行うことができる 結果、ユーザーにとっても問合せの解決までにかかる時間の短縮が期待できます。 チャット返信内容のレコメンド(Chat reply recommendation) ライブエージェントとしてチャット上でユーザーと会話する際、返信内容を自動生成してレコメンドしてくれる機能です。 動作検証 まずは、エンドユーザーとして「ネットワークの調子が悪い」「ルーターが赤く点滅している」「ルーターを交換したい」など自身の抱えている課題を仮想エージェントに問い合わせます。 その後、仮想エージェントによる解決はできなかったという想定で、ライブエージェントへと接続します。 以降は、Service Operations Workspaceにおけるオペレータの操作画面となります。 エンドユーザーからのライブエージェント接続依頼がオペレーターに届いたので「オープン」をクリックしチャットを開始します。 チャットが開始されると、Now Assistによりそれまでにエンドユーザーと仮想エージェントの会話内容が要約されて表示されます。(赤枠) これによりオペレーターは、チャットを遡ることなしに、ユーザーの問い合わせ内容を素早くキャッチアップできます。 以下画像の赤枠部分は、Now Assistによるチャット返信のレコメンドになります。 エンドユーザーが入力したコメントを踏まえて、返信内容を自動生成しレコメンドしてくれます。 オペレーターは必要に応じて、文章を修正してエンドユーザーに返信することが可能です。 問合せ内容が自分自身の担当領域外で解決方法が分からない為、他のオペレーターへとエスカレーションすることにします。 /taというショートカットを使うことで、他のオペレーターへとチャットをエスカレーションできます。 別のオペレーターにエスカレーションの通知が届いたので、「承認」をクリックしてエンドユーザーとのチャットを開始します。 チャットが開始されると、エンドユーザーと仮想エージェント、及び、前担当者とのやり取り内容がNow Assistにより要約されて表示されます。(赤枠) エスカレーション先のオペレーターは、ユーザーの抱える課題、状況を素早くキャッチアップできます。 最終的に解決方法を提示して、チャットを終了します。   おわりに 本記事では、仮想エージェント、ライブエージェントにおけるNow Assistの機能を記載しました。 要約によりオペレーターの状況把握にかかる時間が短縮され、結果エンドユーザーの課題解決までの時間も短縮が期待できる機能だと思いました。 次回は、インシデント対応におけるNow Assistの機能をまとめていきたいと思います。
アバター
SCSKの畑です。 前回のエントリ で触れたアプリケーションにおいて、どのようにテーブルデータを保持していたかに関する補足的内容となります。小ネタです。   アーキテクチャ図 懲りずにいつものやつを。今回のメインは Amazon Redshift、Amazon DynamoDB、Amazon S3 あたりです。   テーブルデータメンテナンス機能要件のおさらい 最初に、改めてテーブルデータメンテナンスの要件を記載します。他、対象テーブルを所管する組織(= Cognito グループ)に属しているユーザのみデータ編集が可能となるような権限管理関連の要件もありましたが、本題にはあまり関係ないので割愛します。 メンテナンス対象テーブルデータの更新機能(≒DML操作) テーブル定義の変更(≒DDL操作)は対象外 テーブル定義の変更時は直接 Redshift に SQL を実行する想定 テーブルのバージョン管理機能  過去バージョンのデータ参照や、バージョン間のデータ比較が可能(テーブル定義が同一の場合のみ) テーブルデータ/定義どちらの変更があった場合でも、新しいバージョンと見なして管理 アプリケーション経由でテーブルデータを更新する際の簡易ワークフロー機能 別ユーザによる承認を以って、Redshift 側に編集したデータの更新が反映される 以上より、こちらも前回のエントリで記載した内容を含みますが、以下2点をアーキテクチャ設計で考慮する必要がありました。 1. より、テーブル定義の変更が行われてもシステム側で柔軟に対応できる必要がありました。また、テーブル定義の変更(≒DDL操作)についてはアプリケーションのスコープ外である以上、アプリケーション外での更新も取り込むことを考慮しておく必要がありました。 2. 及び 3. より、過去バージョンのデータや編集後の承認待ち一時データを保管しておく領域が必要になりました。また、1点目の内容より、アプリケーション外でのテーブル定義の変更に柔軟に対応できることが望ましかったです。 以上を踏まえて、どのようにこの領域を用意するかを検討していました。   第一候補:DynamoDB 当初は DynamoDB を使用する予定でした。 元々アプリケーションマスタとして DynamoDB を使用する予定だったため相乗りすればアーキテクチャとしてもシンプルですし、メンテナンス対象テーブルの編集ステータス管理なども担う都合上、合わせて実データも持てれば利便性もあるのではないかと考えました。また、実は DynamoDB って Redshift と COPY/UNLOAD 文によりテーブルと直接データの入出力ができることを知り、そういう意味でも親和性高いのではないかと。 下記 URL の通り、実は Redshift と COPY/UNLOAD 文で外部ファイル内のデータをやり取りをできるサービスは限定されており、DynamoDB はその一つです。一番ベーシックなのは S3 ですね。 COPY - Amazon Redshift データファイルまたは Amazon DynamoDB テーブルから、テーブルにデータをロードします。ファイルは Amazon Simple Storage Service (Amazon S3) バケット、Amazon EMR クラスターま... docs.aws.amazon.com UNLOAD - Amazon Redshift クエリの結果を、Amazon Simple Storage Service (Amazon S3) の 1 つ以上のファイルにアンロードします。 docs.aws.amazon.com ただ、DynamoDB 上でテーブル自体を保持するようにした場合、表定義の変更にどう対応するのかが課題となりました。実質的に Redshift との二重管理になってしまうため、Redshift 側での表定義変更時にどう対応するかが難しいと感じました。表定義変更自体はアプリケーション側のロジックで検知できるものの、そもそも KVS と RDBMS で根幹の仕組みも異なるため KVS 側で対応していない部分をどのように実装するかが悩ましく。例えば、DynamoDB におけるテーブルのパーティションキー/ソートキーの変更がある場合はテーブルの再作成が必要となりますが、特に UNLOAD の場合にそのようなケースに該当した場合の対応などです。 そもそも、お客さんの AWS 環境における DynamoDB のテーブルの作成/削除の権限がもらえていないというより根本的な問題もあったのですが、仮にこのアーキテクチャで行くと確定していた場合は交渉していたかと思います。それでも NG だった場合は対応を諦めざるを得なかったですが。 このため、対応の柔軟性を考えて DynamoDB のテーブルとしてデータを保持するのではなく、テーブル定義やデータ自体をテーブルの絡む(項目)内に持ってしまうような構成に変更しようとしたのですが、1項目の最大データサイズが 400KB であったため、データ自体を1項目に入れてしまうのは無理だと諦めました。当時はテーブルデータを圧縮する想定がなかったということもありますが、どちらにせよ足りなかったです。それ以前に設計としては無理矢理感があって良くなかったと思うので、結果的には断念することになって良かったと思っていますが・・   第二候補(決定):S3 ということで、DynamoDB 以外ということで丸い選択と考えると、ほぼ必然的に S3 を使用することになった感じです。S3 上に配置したファイル経由で COPY/UNLOAD 文により Redshift とデータ入出力が可能なこと、実質的にファイル単位で情報を保持することになる以上、DynamoDB の項目に記載したような問題が発生しない、の2点が主な理由です。 最も後者については、その分アプリケーション側での実装が必要になるとも言えるのですが、DynamoDB も KVS である以上 RDBMS との機能差異があるため、結果的にそこまでアプリケーションの実装をカバーできなかったのではないかと。 どのような実装がアプリケーション側になったかの詳細については、また別のエントリで書こうと思います。 また、一時テーブルデータや古いバージョンのテーブルデータを世代管理・ハウスキーピングするにあたり、S3 のライフサイクル機能や既存の S3 ハウスキーピング用 Lambda 関数を使い回せるという点もありました。最も、DynamoDB は TTL 設定ができるため、ある程度は代用できるところもあったとは思いますが。 最後に、どのようなファイル構成で Redshift のテーブルを扱っているかを簡単に説明して終わりたいと思います。現在は、下記3種類のファイルをテーブル単位でそれぞれ扱っており、これらの情報を組み合わせてアプリケーション上でテーブルデータを表示しています。 テーブル列定義ファイル 列名(論理名・物理名)やデータ型などの情報を扱っています。 論理名は別情報として定義されているコメントを結合して持ってくるようにしています。 テーブル制約定義ファイル 各制約(PK・UK・FKなど)の情報を扱っています。 SQL 文を含む内容の詳細は 5回目のエントリ を参照ください。 テーブルデータファイル 7回目のエントリ で記載した通り、Redshift と COPY/UNLOAD 文によりテーブルと直接データの入出力を行うため、同 SQL 文で直接扱える JSON Line 形式でファイルを保持するようにしています。 AppSync/Lambda とアプリケーション間でデータをやり取りする際には、AppSync の最大ペイロードサイズを考慮してデータを圧縮するようにしています。 上記のようなファイル構成として扱うことで、Redshift 上のテーブルの定義やデータが変更された場合もアプリケーション側の実装含めて柔軟に対応できるようにしています。また、テーブルのバージョン管理をするにあたり、実質的には Redshift 上のテーブルデータ/定義と、アプリケーションが認識している最新のテーブルデータ/定義(=S3上のテーブルデータ/定義)間の変更有無を検出できる必要がありますが、この仕組みにすることでファイルの内容を精緻に比較することなく、ファイルのハッシュ値のみで比較できるようになったというのも利点の一つでした。もちろん、そのように比較できるように SQL 文を書く必要はありましたが、実装面では幾分楽ができました。   まとめ 今回は正に前回エントリの補足というかそれに関連した小ネタでしたが、まだこのような内容はいくつかあるため、今後も既存のエントリの内容を補完する形で投稿していければと思います。 本記事がどなたかの役に立てば幸いです。
アバター
こんにちは。ひるたんぬです。 突然ですが、皆さんはシャツを着る時に後ろ前をどのように判断していますか? 一般的な判断基準としては首の部分の形状(Vネックやボタンが付いている場合は分かりやすいですよね)や、首の部分についているブランドのタグで判断される方もいらっしゃるのでは無いでしょうか。 ただ、この場合ですと、シャツの首周りを確認するために、わざわざシャツの向きを変えたり、整えたりする必要がありますよね(語彙力が乏しく…通じますかね?)。小さなことですが、大変な作業だよなぁ…と私は勝手に思っています。 私はシャツの裏側についている洗濯表示のタグの位置で判断しています。実は、洗濯表示のタグは必ずと言っていいほど左についているんです¹。 これにより、着る前にシャツの向きを変えることなく、下から裏の洗濯タグの位置を確認し、着ることができます。 少し時短することができました。嬉しいですね。 ¹ 私の人生経験上では左側にしかついていなかったのですが、明確にルールや取り決めなどは無いようです。右側の服が増えたらどうしよう… 参考: 洋服のタグ | さくら中央税理士法人 さて、今回は生成AIを利用するにあたって、ハルシネーションを起こしにくくする手法の一つであるRAGについて、個人的に気になったことがあったので検証してみました。 本記事はあくまで一個人が検証目的で行ったもので、後述する 結果の再現性を保証するものではありません 。 参考程度に捉えていただけますと幸いです。 気になったこと 先述した通り、RAGは生成AIのハルシネーションを起こしにくくするための手法の一つであり、昨今「ハルシネーションを防ぐにはRAGを導入しましょう!」と言ったことをよく耳にしていました。 そこで、私は「RAGの情報そのものがLLMにて学習していた事前知識と矛盾する場合や、RAGの情報内で矛盾していた場合どういう結果になるのだろうか…?」と思い、今回の検証を実施することにしました。 一個人の見解ですが、私は 厳密な事実を求める目的 に生成AIを利用するのは、現時点では否定的な立場です。LLMの性質上、確率に基づいて解を生成しているため、そこには多かれ少なかれ、誤りが発生してしまうことは構造上防げないと考えています。 ※ 今後大きなブレイクスルーが起こった場合はこの限りではありません。 ※ LLMの構造に興味がある方は、 こちら がとても参考になります。 テストケース 上記を整理すると、今回は以下のようなテストケースが考えられます。 今回は知りたいことを”A”, “B”とし、解を”V, W, X, Y, Z”で表しています。また”−”はその情報を持ち合わせていない・与えないことを表します。 パターン LLMの事前知識 RAGの情報① RAGの情報② ①-a A = Z − − ①-b A = Z A = Y − ①-c A = Z A = Y A = X ②-a − B = W − ②-b − B = W B = V パターン①は、LLMの事前知識がある場合、②はない場合です。 また、各パターンの”a”は、一般的な(正しい)使い方の結果を想定しています。 LLMの事前知識の有無は、LLMからの回答をもって判断するものとします。   事前準備 RAG環境の準備 今回の検証を実施するにあたり、RAGの構築が必須となります。今回は比較検証がメインとなるため、RAGの構築につきましては、下記記事を参考に実施しました。 AWSの生成AIで社内文書検索! Bedrockのナレッジベースで簡単にRAGアプリを作ってみよう - Qiita 生成AI、流行ってますね!今みんながやってる「社内文書検索」アプリ、いわゆるRAGアーキテクチャをAWSで簡単に作ってみましょう。1時間程度でサクッと試せるハンズオンです。2025/1/14更新… qiita.com …特に大きな懸念もなく構築することができました。 なお、今回は複数のケースで独立したRAG(ナレッジベース)を作成する必要があるため、バケット内のケースごとにフォルダを分割し、それぞれでナレッジベースを作成しました。 パターン①の題材決め パターン①では、Aというものに対して、既知の解Zと、矛盾する解X, Yを用意する必要があります。 今回はAをりんごとし、Zを果物と定義することにします。そして矛盾する解はそれぞれ「X = 魚類」「Y = 肉類」とします。 数学の定義上、「りんご = 果物」ではなく、「りんご ∈ 果物」と記載することが適切ですが、今回はその厳密性についてはご容赦ください。 パターン②の題材決め パターン②では、LLMがまだ知らない事象について確認する必要があります。 今回は架空の何か「えよぴんぷ」を作り出し、矛盾する解「V = 日本の郷土料理」「W = SCSKの社員」とします。 事前確認としてLLMに「えよぴんぷ」を知っているか確認も取ります。 知らないと答えてくれました。念の為、郷土料理やSCSKの社員か聞いても知らないか確認をします。 知らなかったですね。良かったです。 造語を作って聞いてみてもハルシネーションが多く、この返答を出してくれる単語を創作するのが実は一番大変でした。半濁音が多いのはなんとなく、です。 RAGに与える資料作り 今回は各要素について、「りんごは果物です。」等といった記述のみをした文書ファイルをそれぞれ作成し、与えることにします。 一例を以下に添付します。 これだけのPDFファイルも中々シュールです。   検証 準備も整ったので、一つずつ検証をしてみましょう。 パターン①-a まずは、既知の情報のみでの確認です。シンプルな質問で確認をします。 ▼ A = Z の確認 ▼ A ≠ X の確認 ▼ A ≠ Y の確認 ▼ Aが「X, Y, Z」のどれに該当するかの確認 …もちろん正しいです。 パターン①-b 続いて、矛盾する情報を一つ与えた場合について確認をしてみます。 ★ 「A = Z」と「A = Y」の情報を持っている場合です。 ▼ AとZの関係 ▼ AとXの関係 ▼ AとYの関係 ▼ Aが「X, Y, Z」のどれに該当するかの確認 …LLMは自身に「常識」を持っており、それと照らし合わせて判断していることが伺えました。 常識を基に、矛盾した情報に惑わされることなく「りんごは果物である」という事実を一貫して述べています。 パターン①-c 更に矛盾する情報を与えた場合の確認です。 ★ 「A = Z」と「A = Y」「A = Z」の情報を持っている場合です。 ▼ AとZの関係 ▼ AとXの関係 ▼ AとYの関係 ▼ Aが「X, Y, Z」のどれに該当するかの確認 パターン①-bと同じように、「りんごは果物である」というLLMの主張は変わりませんでした。 また、ナレッジベースの情報に矛盾があるということも指摘してきました。 パターン②-a ここからは、LLMに事前知識がない場合の検証です。 ★ 「B = W」の情報のみを持っている場合です。 ▼ BとWの関係 ▼ BとVの関係 ▼ Bが「V, W」のどれに該当するかの確認 きちんとRAGが動作し、えよぴんぷがSCSKの社員であることを答えてくれました。 料理にならなくて安心しました。 パターン②-b 更にLLMに矛盾した情報を与えてみましょう。 ★ 「B = W」と「B = V」の情報を持っている場合です。 ▼ BとWの関係 ▼ BとVの関係 ▼ Bが「V, W」のどれに該当するかの確認 ここで、BとWの関係について、一方のみの情報で解を出す事例がありました。 何回か聞いてみましたが、この状況は変わりませんでした。 そこで、BとVの関係についても何度か質問してみたところ、以下のような回答を出すことがありました。   まとめ 今回の検証の結果をまとめます。 パターン LLMの事前知識 RAGの情報① RAGの情報② 結果 ①-a A = Z − − A = Z のみ出力 ①-b A = Z A = Y − A = Z のみ出力 A = Y は誤った情報と回答 ①-c A = Z A = Y A = X A = Z のみ出力 A = X, Y は誤った情報・矛盾していると回答 ②-a − B = W − B = W のみ出力 ②-b − B = W B = V 結果が安定せず   考察・今後に向けて ここからは私個人の完全なる推測です。 今回は、ナレッジベースに与える情報として、「AはYです。」といった事実のみ与えました。 そのため、パターン①のように事前知識がある場合、情報量が少ないナレッジベースの内容は虚偽として捉えられた可能性が高いです。 一方、パターン②のようにLLMが事前確認として持ち合わせていない事象に対しては、情報量が(恐らく)等しい事象を与えたため、LLMが判断に迷い、様々な結果が出力されたと考えています。 今後はパターン①に対抗するため、事前知識に対抗しうる情報量をナレッジベースに与えた場合や、パターン②において情報量に偏りをもたせた場合の挙動について調査をすると、また面白い結果が出るのかなと感じた次第です。   おわりに この記事を執筆していると、ほんの少しですが学生時代の研究生活を思い出しました。(今回の検証は、厳密性・再現性の観点から見ると本当にお遊び程度ですが…) この内容についても学術的に研究されている論文もあります(アーカイブですが)ので、興味がある方は読んでみると面白いかもしれません。私も少しだけですが読みました。 ※ 今回の検証結果の一部は、下記論文の内容とも合致していました。 https://arxiv.org/pdf/2305.13300 arxiv.org
アバター
本記事は、以下記事の続編です。 Amazon Nova を触ってみた (テキスト生成編) 昨年のre:Invent 2024にて、Amazon Bedrockでのみ利用可能なモデルとしてAmazon Novaが発表されました。本記事では、Amazon Novaシリーズの中でテキスト生成が可能な3つのモデル(Micro、Lite、Pro)についてまとめました。Amazon BedrockマネジメントコンソールとConverse APIから実行する方法をご紹介します。 blog.usize-tech.com 2025.01.29 本記事では、画像生成モデルAmazon Nova Canvas、動画生成モデルAmazon Nova Reelについてまとめました。 Amazon Novaとは? Amazon Novaは、フルマネージドサービスであるAmazon Bedrockにて利用可能な、Amazonが開発したモデルです。 テキストや画像、動画をプロンプトとして与えることにより、テキスト生成だけでなく、画像生成や動画生成も可能です。 本記事投稿時点では、Canvas、Reelはバージニア北部でのみ利用可能です。 Amazon Nova Canvas テキストからの画像生成はもちろんのこと、既存の画像をもとに新たな画像を生成できるマルチモーダルなモデルです。 画像のある部分だけを別の画像へ置換、画像の特徴を維持したまま別のバリエーションで再生成、背景の削除など簡単な画像編集も可能です。 Amazon Novaユーザーガイドには、英語のみ対応と記載されていますが、実際には日本語にも対応しているようです。 入力形式 テキスト、画像 最大入力文字数 1024 最大入力画像サイズ 25MB サポートされている画像入力形式 PNG、JPEG 最大入力画像サイズ 25MB 画像1枚あたりの料金 (解像度1024×1024まで) USD 0.04 画像1枚あたりの料金 (解像度2048×2048まで) USD 0.06 Amazon Nova Reel テキストや画像から動画を生成できる動画生成モデルです。 本記事執筆時点では、最大6秒間の動画を生成できますが今後のアップデートにより、最大2分間の動画生成、高解像度への対応、ストーリボード機能による複数シーンの統合などがアナウンスされています。 また、Canvas同様にReelも日本語に対応しています。 入力形式 テキスト、画像 最大入力文字数 512 最大入力画像サイズ 25MB 解像度 1280×720 フレームレート 24fps 生成動画の長さ 最大6秒まで 生成された動画1秒あたりの料金 USD 0.08 実際に触ってみる モデルアクセス有効化 まずはモデルアクセスを有効化します。 リージョンをバージニア北部に変更し、Bedrockのメニューから「モデルアクセス」をクリックします。 以下のような画面が表示されたら「特定のモデルを有効にする」をクリックします。 「Nova Canvas」、「Nova Reel」にチェックを入れて「次へ」をクリックします。 「送信」をクリックします。 アクセスのステータスが「アクセスが付与されました」となっていればモデルアクセス有効化完了です。 Amazon Nova Canvasを使ってみる 「モデルを選択」をクリックします。 「Nova Canvas」を選択して「適用」をクリックします。   左側の設定では実行するアクションや生成する画像のサイズ、枚数、色の指定などが可能です。 「3匹の犬が公園で遊んでいる画像」をリクエストしてみます。 画像の一部を変更したい場合は、「バリエーションを生成」を選択して、プロンプトに変更内容を入力すると新たな画像が生成されます。生成された画像にばらつきはあるもののリクエスト通り毛並みが茶色になりました。 次は左側に写っている犬を画像から削除したいと思います。 「オブジェクトを削除」を選択すると青白い枠が表示されるので、削除したいオブジェクトを枠で囲みます。 リクエストどおりに左側に写っている犬が削除されました。 また、「背景を削除」を実行すると簡単にPNG透過された画像を生成できます。 Amazon Nova Reelを使ってみる 続いて動画生成をやってみます。まずはモデルを「Nova Reel」に変更します。 プロンプトを入力して実行すると生成が開始しました。 動画は5分ほどで生成され、左側に表示されているS3に保存されます。 可愛いわんちゃんが遊んでいる動画が生成されましたが、あまり動きがなく背景だけ動いている動画になってしまったのが少し残念です。。。 document.createElement('video'); https://blog.usize-tech.com/contents/uploads/2025/02/output.mp4 最後に先ほどCanvasで作成したこちらの画像をもとに動画を作成してみたいと思います。 散歩している動画をリクエストしたのですが、先頭の1匹だけが動いている動画が生成されました。。。 プロンプトを1文で記載していることも影響しているとは思いますが、精度が課題かもしれません。 https://blog.usize-tech.com/contents/uploads/2025/02/output-1.mp4 まとめ Amazon Novaシリーズの中で画像と動画生成が可能な2つのモデルについてまとめました。 画像は10秒程度、動画は5分程度で簡単に作成できる魅力的な生成モデルと感じました。 プロンプトやパラメータの調整、入力に画像を利用するなどの工夫で生成精度を上げることができれば、広告やプレゼンテーションなどに活用できる可能性もあると思います。 まだリリースされたばかりのモデルであり、今後のアップデートも発表されているので楽しみに待ちたいと思います。
アバター
Google Cloud環境では、多くの方がデータの保存や共有のためにCloud Storageサービスを利用していると思います。特に、データアーカイブやログ保管の用途でCloud Storageを使用する際には、データの世代管理など非機能要件の検討が重要だと思います。 今回は、先日Cloud Storageバケット使用時に、世代管理の設定を行った際の実装方法を振り返るとともに、CLIでの実装方法を整理してみたいと思います。 概要 まず、バケットの世代管理には、 バージョニング と ライフサイクル という機能が必要となります。 それぞれの機能について説明します。 バージョニングとは Cloud Storageバケット内でオブジェクトの異なるバージョンを保持する機能です。バージョニングを有効にすると、オブジェクトを上書きまたは削除した場合でも、過去のバージョンを非現行バージョンのオブジェクトとして保持し、必要に応じて復元することができます。バージョニングを使うことで、データの誤削除や意図しない変更から保護できます。 詳しくは、以下をご確認ください。 オブジェクトのバージョニング  |  Cloud Storage  |  Google Cloud cloud.google.com ライフサイクルとは Cloud Storageバケット内のオブジェクトについて自動管理するためのルールを設定する機能です。経過日数やオブジェクトのバージョン数など、特定の条件に応じてストレージクラスを変更したり、オブジェクトを削除したりできます。これにより、コストの最適化やストレージ管理の効率化が実現できます。 詳しくは、以下をご確認ください。 オブジェクトのライフサイクル管理  |  Cloud Storage  |  Google Cloud cloud.google.com よって世代管理の実現のためには、バージョニングの有効化と非現行バージョンの扱い方のルール設定を組み合わせることが重要です。   実装例 以下にて、CLIを使用した設定方法を示します。 バージョニングおよびライフサイクルの設定は、バケット単位で行います。 ①バージョニング有効化 以下のコマンドでバージョニングの有効化をします。 ※デフォルトではバージョニングの設定はオフになっています   gcloud storage buckets update gs://[バケット名] --versioning   例: $ gcloud storage buckets update gs://test-generation-management --versioning ⠼Updating gs://test-generation-management/... Completed 1   ②バージョニング有効化の確認 以下のコマンドでバージョニングの有効化を確認できます。   gcloud storage buckets describe gs://[バケット名] --format="default(versioning_enabled)"   例: $ gcloud storage buckets describe gs://test-generation-management --format="default(versioning_enabled)" versioning_enabled: true   ③ライフサイクルルールの作成 適用するライフサイクルルールを含むJSONファイルを作成します。 今回は、 「新しいバージョンを3つ保持しつつ、非現行バージョンとなってから1日経過したオブジェクトを削除する(削除対象は非現行バージョンのみ)」 という条件でルールを設定します。 (例)test-lifecycle.json { "lifecycle": { "rule": [ { "action": {"type": "Delete"}, "condition": { "daysSinceNoncurrentTime": 1, "isLive": false, "numNewerVersions": 3 } } ] } }   なお、設定したいライフサイクルルールのアクションやオブジェクトの条件についての詳細は以下のサイトをご確認ください。 オブジェクトのライフサイクル管理  |  Cloud Storage  |  Google Cloud cloud.google.com   注意点 条件の設定方法で、削除が行われるタイミングや対象が異なりますのでご注意ください。 { "lifecycle": { "rule": [ { "action": {"type": "Delete"}, "condition": { "numNewerVersions": 3, "isLive": false } }, { "action": {"type": "Delete"}, "condition": { "daysSinceNoncurrentTime": 1 } } ] } }   例として、先述した「test-lifecycle.json」では、記述しているすべての条件を満たした場合にのみルールが実行されますが、上記のようにルールを設定すると、各条件が独立しているため、どちらかの条件を満たすだけでルールが実行されます。つまり、保持したい新しいバージョンの数に限らず1日経過すると すべてのオブジェクトが削除対象 となってしまいます。   ④ライフサイクルルールの適用 以下のコマンドで、作成したJSONファイルを使用してライフサイクルルールを適用します。   gcloud storage buckets update gs://[バケット名] --lifecycle-file=[手順③で作成したJSONファイルのパス]   例: $ gcloud storage buckets update gs://test-generation-management --lifecycle-file=test-lifecycle.json ⠶Updating gs://test-generation-management/... Completed 1   ⑤ライフサイクルルール適用の確認 以下のコマンドでライフサイクルルールの適用を確認できます。   gcloud storage buckets describe gs://[バケット名] --format="default(lifecycle_config)"   例: $ gcloud storage buckets describe gs://test-generation-management --format="default(lifecycle_config)" lifecycle_config: rule: - action: type: Delete condition: daysSinceNoncurrentTime: 1 isLive: false numNewerVersions: 3   最後に バージョニングとライフサイクルの設定は、一見簡単に思えるかもしれませんが、実際に設定を行う際には詳細な条件設定が必要であり、意外と複雑です。適切な条件を設定することで、効果的なデータ管理と保護につなげることができると思います。 また、今回はGoogle CloudのCloud Storageバケットの世代管理について整理しましたが、AWSのストレージサービスであるS3バケットでも同様に、世代管理の設定が可能です。S3のライフサイクルルールでも JSONファイルを使用して設定を行い、CLIでルールを適用できます。 ただし、それぞれのアクションの選択肢や詳細な条件設定の方法には違いがあります。たとえば、S3ではオブジェクトタグを使って、特定のタグが付けられたオブジェクトに対してのみのライフサイクルルールの 適用が可能です 。一方、Cloud Storageでは現時点でタグを使用したフィルタリングオプションはありません。また、S3では非現行バージョンに対する制御がアクションの一部として設定できるのに対し、Cloud Storageでは非現行バージョンを条件の一部として設定するため、オブジェクトの制御方法が異なります。 このような違いを理解し、両方のクラウド環境でのストレージサービスの世代管理に柔軟に対応できるようにすることも重要だと思いました。 この記事が、Cloud Storageをストレージ先として選択する際や、非機能要件に基づくバケット管理方法の検討時の参考となり、 スムーズな設計と構築のお役に立てれば嬉しいです。
アバター
SCSK株式会社では 2025/1/21(火)と1/22(水)の2日間 ジョブの見える化を加速させる!JP1最新バージョンのライセンス&新機能解説セミナー と題して、JP1の最新バージョンのライセンス及び新機能の解説、 そしてJP1との親和性の深い高可用性製品としてLifeKeeperの紹介を行ったセミナーを JP1部隊とLifeKeeper部隊で協同開催いたしました。(二日間とも同内容) 本記事では JP1 × LifeKeeper セミナーの開催レポートを行いたいと思います! セミナー概要 項目 内容 開催日 2025年 1月21日(火)11:00~11:45 2025年 1月22日(水)14:00~14:45 開催場所 オンライン(Zoom)   セミナー要旨 昨年30周年を迎えた統合システム運用管理ツールであるJP1。 運用管理ソフトウェア市場では長年国内トップシェアを誇り、 国内運用管理市場をけん引し続け多くの企業のシステム運用を支えています。 しかし、JP1の導入を検討する際に、 「ライセンス体系や費用が複雑で分かりにくい」 「クラウド環境でもJP1は利用できるのか?その場合のライセンスはオンプレミス環境の場合と同じなのか?」 「災害対策環境でもJP1は組み込めるのか?」 「JP1の信頼性や可用性を高める方式はあるのか?」 と、このような疑問を抱かれるケースがございます。 そこで、JP1の最新版であるバージョン13のライセンス体系や費用を様々な構成における 具体的な試算例を交えた解説、そして冗長化構成例について紹介し、 JP1に関心をお持ちの方にとって最適な情報を、20年以上のJP1導入実績を基に、短時間で分かりやすく解説をするセミナーとなっております。   【ご参加いただいたお客様】 ・JP1について上記のような疑問点をお持ちの方 ・JP1の導入を検討中、もしくは既に導入済みの方 ・ジョブ管理製品について情報収集をされている方 ・JP1の信頼性や高可用性の担保を検討されている方   【アジェンダ】 ・JP1最新バージョンの機能解説 ・JP1ライセンス体系・費用体系の解説 ・ライセンス試算例のご紹介 ・JP1の冗長化構成例:JP1とLifeKeeper ・各種ご案内   セミナー内容一部ご紹介 オンラインでの開催で、40名弱の方からお申込みをいただきました。 今回参加頂いたお客様はJP1導入を検討もしくは利用しているお客様となります。 そのお客様に向け、JP1との親和性の深く高可用性が実現できるソリューションとしてLifeKeeperをご紹介いたしました。 本セミナーで講演いたしましたLifeKeeper部分について一部内容をご紹介させていただきます。 LifeKeeperの講演としては以下内容についてお話させていただきました。 ●JP1とLifeKeeper   -冗長化/高可用性について   -JP1高可用性ソリューション   -LifeKeeper/DataKeeperについて   -冗長化構成例 ●ご案内   -LifeKeeperに関するお得なキャンペーン情報   項目といたしましては、JP1とLifeKeeperと題し、 冗長化/高可用性についてのニーズの高まりをご説明させていただき、 LifeKeeperの特徴や基本動作についての製品紹介をさせていただきました。 ①LifeKeeper システムの二重化でビジネス損失を最小限に! システムを監視し、稼働系の障害時に待機系に自動切替を行うHAクラスターソフトウェア。 稼働系システムに異常が発生した際、待機系に引継ぎを行うフェイルオーバーという動作をし、 システムが停止する時間を大幅短縮し、夜間・休日のシステム停止による運用負担を大きく軽減できます! ②DataKeeper データをリアルタイムに複製! 稼働中サーバーのデータを待機系サーバーへリアルタイムにレプリケーション(複製)するソフトウェア。 LifeKeeper又はWindows Server Failover Clusterring(WSFC)と連携し、 仮想的な共有ストレージとして認識させることで、共有ストレージを構成できないパブリッククラウドでも利用可能となります! ※セミナー資料一部抜粋   最後にご案内というところで、LifeKeeper構築キャンペーンの宣伝をさせていただきました。 SCSKでは現在、AWSを利用中で冗長化構成を検討中のお客様を対象とした 「 SCSK LifeKeeper 導入キャンペーン 」を 2025年3月まで の 期間限定で開催しております! いまなら2ノード冗長化の構成を 特別価格の30万円 にて構築作業をさせていただいております。 対象環境がAWS 対象OSが、RedHat Enterprise for Linux、Windows Server 対象ミドルウェアが、JP1、HULFT、MySQL、Oracle、PostgreSQL、SVF、Zabbix のいずれか のお客様に限定させていただいておりますが、ぜひこの機会にLifeKeeper導入をご検討下さい!という旨をセミナーでもご紹介させていただきました。 残り期間も少なくなっておりますが、少しでも興味のあるかがいらっしゃいましたら、 詳細に関しましては以下サイトに記載しておりますので、ぜひご覧いただき、お気軽にお問い合わせください。 【2025年3月まで開催中】SCSK LifeKeeper導入キャンペーン| SCSK株式会社   最後に 今回、JP1とLifeKeeperのセミナーを開催したことをご紹介させていただきました。 今後もLifeKeeperに関するセミナーを開催予定となりますので、乞うご期待ください。
アバター
SCSKでは本日(2025/2/14)、当社独自開発の「Catoクラウド AIチャットボット」をご提供開始しました。 プレスリリース Catoクラウドの問い合わせに対応するAIチャットボットを提供開始 ~お客様がドキュメントを検索する時間を約70%削減~ このAIチャットボットは、Cato公式のKnowledge Base等(※)に加え、当社の独自コンテンツである FAQサイト と、この技術ブログ「TechHarmony」内のCato関連記事を情報ソースとしており、Catoクラウドに関する質問に日本語で応答します。 本日のリリースに先行して社内のCato担当者で利用してきましたが、 情報の検索が大幅に効率化でき、現在ではCatoクラウドの運用において手放せないツールとなっています。 この記事では、AIチャットボットの便利さや活用方法、開発の背景などをご紹介します。 ※Cato Networks公式の情報は Cato Networksに許諾を得た上で取り込みを行っています これがSCSK Catoクラウド AIチャットボットです 実際の画面は、このように一般的なAIチャットです。 画面左側にはチャットの履歴が表示されており、過去の問い合わせ内容を確認できます。 また、画面上部にて、参照する情報ソースを切り替え可能です。 ソース選択 参照する情報 利用シーン Cato公式情報のみ利用 Cato公式のKnowledge Base、Master Service Agreement等 知りたい機能があって、その機能のKnowledge Base等を探したいとき すべての情報を利用 Cato公式のKnowledge Base、Master Service Agreement等に加え、SCSKのFAQサイト、技術ブログ記事 トラブルの切り分けをしたいとき 構成や利用例など機能を特定しない質問をしたいとき 利用例 さっそくCatoクラウドの機能について問い合わせをしてみましょう。 機能の説明の後、 「参考情報」として参照したURLを明示 します。AIの回答で概要を把握した後、より詳細を知りたい場合はKnowledgeを見て確認できます。 次に、トラブルの相談例です。情報は多いほうが良いため、ソースを「全ての情報を利用」としてみましょう。 トラブルシュートは、Knowledge Baseよりも当社のコンテンツに情報が多いため、ブログ記事とFAQを参照した回答が返ってきました。この場合も参照元へのリンクが明示されます。 このように、AIチャットボットは、問い合わせ内容に適切な回答を返すのはもちろん、情報元の確認も簡単となっており、疑問・問題のスムーズな解決を支援します。 AIチャットボット開発・リリースの経緯 SCSKではCatoクラウドのサポート窓口を設け、ご不明点へのご回答やトラブルシュートを行っておりますが、いただくお問い合わせの一部は、CatoのKnowledge Baseや当社FAQに掲載のある内容でした。お客様は、知りたい情報にたどり着けないためにお問い合わせいただいており、この背景には以下のような問題がありました。 Knowledge Baseは英語のため、検索には適切なキーワードを英語で指定する必要がある。 Knowledge Baseの情報量が多く、多数のページが検索Hitするため、その中から必要な情報を探し出すことが難しい。 当社FAQサイトや技術ブログは日本語だが、Knowledge Baseを補う目的で作成しているため、Knowledge Baseと重複する情報は掲載しておらず、網羅性がない。 このため、 複数の情報ソースをうまく検索しないと情報が得られない 状況でした。 そこで、 すべてのソースを横断的にかつ自然言語で検索する手段として、このAIチャットボットを開発 しました。開発後、以下のテストフェーズを経て効果測定とチューニングを行い、今回の正式リリースに至っております。 Ph1 社内でのテスト利用 社内のCatoクラウド担当にて利用し、問い合わせ対応の3割程度がAIチャットボットで解決できること、また情報の検索効率が大きく上がることを確認。 ※ Cato Knowledge Baseを含む公式文書のRAGへの取り込みについては、Cato Networks社へ事前に許可を得て実施しています。 Ph2 一部お客様での先行利用 テストをご快諾いただいた一部のお客様にリリース。いただいたフィードバックより、以下のような点を改善。 回答が英語になる場合があったため、常時日本語で回答するよう設定 AIが回答できない場合は、サポート窓口へのお問い合わせをおすすめするよう設定 Catoクラウドに関連しない質問には回答はしないよう制限していたが、ネットワークやセキュリティの一般的な質問には回答するよう緩和 Ph3 先行利用を拡大 さらに数社のお客様に段階的にリリース。以下のようなご感想をお知らせいただき、お客様における導入効果を確認。 Knowledge Baseの検索では欲しい情報にたどり着けないことがあったが、AIチャットボット経由だと日本語で聞けて、適切なKnowledgeへのリンクを返してくれるので便利。 サポートへの問い合わせ前にAIチャットボットに聞いてみるようにしたところ、解決できるものが多くあり、問い合わせの手間が省けた。回答の精度も高いと感じる。 不明点があるときに、Knowledge Base・FAQ・技術ブログ等をそれぞれ探す必要があったが、AIチャットボットが横断的に検索してくれるのでとても便利。検索にかけていた時間が70%程度削減された。 Ph4 正式リリース 当社にてCatoクラウドをご利用いただいているすべてのお客様向けにリリース。 このAIチャットボットは、お客様のCatoクラウド運用の効率化に大きく寄与するものと考えております。 Catoの「AIアシスタント」との違いは? ところで、2025年1月にCatoが「AIアシスタント」をリリースしており、CMA(Cato管理画面)からご利用が可能です。 【Catoクラウド】新機能「AIアシスタント」がリリース Catoクラウドより、2025年1月6日のアップデートにてAIアシスタントがリリースされました。AIアシスタントの実際の使用感や回答精度などについて記載しています。 blog.usize-tech.com 2025.01.30 AIアシスタントも回答精度が高く日本語に対応しているため使いやすいですが、以下のような機能差異があるため、当社内では2つのAIを使い分けしています。 機能 CMA AIアシスタント SCSK AIチャットボット AI機能へのアクセス方法 CMAからアクセスできる 専用のWebサイトへのログインが必要 情報ソース Cato Knowledge Base Cato Knowledge Base、MSA等 +SCSK独自コンテンツ 回答の保存 回答の履歴が保存されない。 ページの移動で回答が消えてしまうため、回答を見ながらのCMAの操作等ができない。 回答の履歴が保存される。 チャットでやりとりをしながらCMAの操作ができる。 使い分けシーンとしては、CMA操作中にちょっとした仕様確認をしたいときにはCMA上のAIアシスタントを、トラブルシュートなどの長いやり取りや、CMAと並べて確認作業をしたいときはSCSKのAIチャットボットを利用する場面が多いです。どちらもいまや運用に欠かせません。 最後に SCSKのAIチャットボットは、当社の「Catoクラウドマネージドサービス」をご契約のお客様に提供しております。 Catoクラウドの運用において強力なご支援となるツールですので、ぜひご活用いただき、フィードバックをお寄せいただけますと幸いです。 また、SCSKでは、今後も日本のお客様にCatoクラウドをご活用いただけるよう、 Cato Academy や 動画コンテンツ の日本語化を検討していきます。
アバター
こんにちは SCSK株式会社の坂木です。 ところで、社内資料の管理、効率的ですか? 様々な形式の文書が散在し、必要な情報を探すのに時間を取られていませんか? ファイルサーバーの奥底に埋もれどこにあるか分からない、バージョン管理が混乱する、などといった課題を抱えていませんか? これらの非効率は、業務の生産性低下に直結します。 今こそ、社内資料の一元管理体制を見直しましょう! ということで、 AWS Bedrockのナレッジベース を用いた資料の一括管理およびその検索方法をご紹介します! Amazon Bedrockについて Amazon Bedrockは、AWSが提供するフルマネージドサービスで、簡単に生成AIアプリケーションを構築できます。基盤モデルと呼ばれる大規模言語モデルをAPI経由で利用可能で、テキスト生成やチャットボット、要約、翻訳など、多様なユースケースに対応しています。 特に便利なのが、ナレッジベース機能です。ナレッジベースとは、社内文書やFAQなど、組織固有の情報を集めたデータベースのことです。Bedrock と接続すれば、AI がナレッジベースの内容を学習し、より精度の高い回答や情報を生成できます。   事前準備 今回は、「データ1.txt」「データ2.xlsx」「データ3.docx」の3つのファイルをもとにデータベースを作成します。 各ファイルには料理のレシピが記載されています。   S3バケットを作成し、対象のデータをアップロードします。 このとき、ナレッジベースにサポートされているファイルの拡張子は 「.txt」「.md」「.html」「.doc/.docx」「.csv」「.xls/.xlsx」「.pdf」 となります。これら以外の拡張にて管理しているファイルは、一度拡張子を変換してからS3へアップロードする必要があります。 Amazon Bedrock ナレッジベースデータの前提条件 - Amazon Bedrock ナレッジベースにデータを使用する前に、必要な前提条件について説明します。 docs.aws.amazon.com   ナレッジベースの作成 Bedrock/ナレッジベースから、画像の画面へ遷移し 「ナレッジベースを作成」 を選択します。   今回はデータソースをS3へ保存しているため、Choose data sourceは 「Amazon S3」 を選択します。 その他の選択肢はデフォルトで、「次へ」を押します。   S3のURL 事前準備にて作成したS3バケットを選択します。 Parsing strategy 今回はデータソースがテキストベース資料のみのため、テキストのみを解析する 「default parser」 を選択します。データソースに画像を含めている場合はFoundation modelsを選択することで、画像の解析が可能となります。 データソースの解析オプション - Amazon Bedrock 解析とは、ドキュメントとその意味のあるコンポーネントの解釈を指します。Amazon Bedrock ナレッジベースには、取り込み中にデータソースを解析するための以下のオプションがあります。 docs.aws.amazon.com その他の選択肢はデフォルトで、「次へ」を押します。   今回は埋め込みモデルの中で最も料金の安い 「Titan Embeddings G1」 を選択します。その他の選択肢はデフォルトで、「次へ」を押します。 基盤モデルを使用した生成 AI アプリケーションの構築 – Amazon Bedrock の料金 – AWS オンデマンドやプロビジョニングスループットなどの Amazon Bedrock の料金モデルの詳細情報と、AI21 labs、Amazon、Anthropic、Cohere、Stability AI などのモデルプロバイダーの料金内訳をご覧... aws.amazon.com   設定を確認してナレッジベースを作成します。以上で、ナレッジベースの作成は完了です。   検索 続いて、作成したナレッジベースを用いてデータソースの内容を検索していきます。 作成したナレッジベースの画面から、生成AIモデルを選択します。筆者はClaude AI推しなので今回は 「Claude 3.5 Sonnet 」 を選択しました。   ナレッジベースを作成後、デフォルトの状態ではデータソースが同期されていません。 そのため、データソースの項目から対象のデータソース(今回の場合だと事前準備で作成したs3)を選択し、同期ボタンを押します。また、 S3に追加の資料をアップロードした場合は、 追加のたびに同期ボタンを押して最新のS3の状況を反映させる必要があります 。   では、いよいよ検索していきます。「データ1.txt」に記載のあるスクランブルエッグの作り方について聞いてみようと思います。 データ1.txtには「ボウルに卵を割り入れ、塩とコショウを加えて混ぜる。フライパンにバターを溶かし、卵液を入れる。中火でかき混ぜながら、好みの固さになるまで加熱する。」という手順が記載されていたため、同様の回答が出力されれば成功です。 聞いてみた結果、 言葉は多少違いますが概ね同じ内容の出力が得られました。また、[1]をクリックすると回答に際してどのファイルを参照したのか分かります。そのため、 質問に対して回答となる社内資料をすぐに見つけられ、ファイルサーバから対象の資料を探す手間が省けます。   次に、データソースにない料理レシピである「ます寿司」の作り方について聞いてみようと思います。 聞いてみた結果、ます寿司の作り方はデータソースに無いと返されました。データソースにナレッジが 無い場合は、web上の精度が曖昧な回答をするのではなく、データソースに無いと回答をもらえるようです。そのため、 提供される情報は登録済みのデータに基づいており、 捏造や誤った情報を返すリスクが抑えられます。   まとめ 本記事ではAmazon Bedrockのナレッジベースを用いた社内資料管理方法について紹介しました。 ナレッジベースを用いることで資料を探す手間を省け、より短時間で確認したい情報へたどり着くことができます。すなわち、生産性の向上に寄与しているのではないでしょうか。 ちなみに、ナレッジベースはOpenSearch Serverlessの料金や検索ごとに料金が発生するため、生産性と一緒にコストも上がったります。要注意です。 最後までお読みいただきありがとうございました!
アバター
概要 Azureの既存Prepaymentから新規Azureテナントのサブスクリプションを払い出してみました。 Microsoft Learnに記載されている手順を参照するだけですが、私が対応した際につまづいたポイントや補足事項を残します。 この手順はいろいろなライセンス形態の中での一例でしかないため、正式な手順はライセンス販売企業様の案内に沿っていただければと思います。 登場するリソース 既存Prepaymentが紐づくテナントA(作成済み前提) テナントAで新規作成するアカウントB 新規作成するテナントB テナントB上で新規作成するサブスクリプションB 用語や概要については以下資料を参照ください。 Microsoft Azure利用ガイド 手順、補足 1.テナントBを新規する。 下記URLから新規テナントBを作成する。 Microsoft 365 E3 (Teams なし) ポイント1→本人確認のセキュリティチェックで電話番号を登録しSMS認証か音声通話認証を実施するのですが、エラーで弾かれ接続環境を変えることで解消しました。   2.テナントAでアカウントBを作成し有効化する。 ・アカウント所有者の登録(エンタープライズ管理者の操作) Azure portal での EA 課金管理 – Microsoft Cost Management | Microsoft Learn ポイント2→アカウントの追加の中で指定するアカウント所有者のメールを新規作成したテナントBのユーザのユーザープリンシパル名を指定します。 この次の手順のアカウントの有効化では2時間半ほどかかりました。 ポイント3→有効化後テナントBのアカウントのプロパティにテナントAの課金アカウント情報も表示されます。   3.テナントBでサブスクリプションBを新規作成する サブスクリプションの作成(上記操作で登録したアカウント所有者での操作) Enterprise Agreement サブスクリプションを作成する – Azure Cost Management + Billing | Microsoft Learn つまづきポイントは特にありませんでした。 以上となります。
アバター
こんにちは、なべです。 最近レトルトカレーにはまっていて、名店のレトルトカレーの食べ比べをしています。 現在AWS環境のIaC構築を推進しており、EC2の非機能周りも自動化で実装されると嬉しいなと思いました。 関連の検索をしても非機能周りの自動実装が無かったので、私の方でログ管理のスクリプトを作成してみました。 概要 EC2起動時にユーザーデータを実行し、以下を設定します。 なお、前提としてWindowsServerであること、CloudWatchAgentをインストールするためインターネットやモジュール取得先のS3につながる環境があること、環境によっては必要なVPCエンドポイント、IAMロールが割り当てられている事が前提の条件となりますが、こちらは今回割愛します。 <CloudWatchAgent設定> ①CloudWatchAgentのインストール ②CloudWatchLogsへの出力設定(JSON) ③CloudWatchAgent起動設定 <S3イベントログアップロード設定> ①イベントログアップロードスクリプト配置 ②タスクスケジューラ設定 ③AWS Tools for PowerShellのインストール 概要図はこちらです ログはいずれもSystem,Application,Securityログを送信します。 やってみましょう 今回設定するユーザーデータスクリプトはこちらです。 スクリプト内の以下6所は要件に合わせて任意で設定いただく箇所になります。 ・ロググループ名 ・スクリプト配置パス ・任意のプレフィックス ・任意のプレフィックス ・アップロード先S3バケット名 ・タスク実行時間 # タイムゾーンを東京に設定 Set-TimeZone -Id "Tokyo Standard Time" # CloudWatch Agentのダウンロード Invoke-WebRequest -Uri "https://amazoncloudwatch-agent.s3.amazonaws.com/windows/amd64/latest/amazon-cloudwatch-agent.msi" -OutFile "amazon-cloudwatch-agent.msi" # MSIパッケージのインストール Start-Process msiexec.exe -Wait -ArgumentList "/i amazon-cloudwatch-agent.msi /qn" # # 5回までフォルダの存在を確認する # for ($i = 0; $i -lt 5; $i++) { # # フォルダの存在を確認 # if (Test-Path -Path "C:\ProgramData\Amazon\AmazonCloudWatchAgent\Configs") { # break # } else { # Start-Sleep -Seconds 5 # } # } # CloudWatch Agent設定をJSONとして保存 $configJson = @' { "agent": { "metrics_collection_interval": 60, "run_as_user": "System" }, "logs": { "logs_collected": { "windows_events": { "collect_list": [ { "event_name": "System", "event_levels": ["ERROR", "WARNING", "INFORMATION"], "log_group_name": "/nabe/tokyo/ec2/system", "log_stream_name": "{local_hostname}_{instance_id}" }, { "event_name": "Application", "event_levels": ["ERROR", "WARNING", "INFORMATION"], "log_group_name": "/nabe/tokyo/ec2/application", "log_stream_name": "{local_hostname}_{instance_id}" }, { "event_name": "Security", "event_levels": ["ERROR", "WARNING", "INFORMATION", "CRITICAL"], "log_group_name": "/nabe/tokyo/ec2/security", "log_stream_name": "{local_hostname}_{instance_id}" } ] } } }, "metrics": { "metrics_collected": { "Memory": { "measurement": [ {"name": "% Committed Bytes In Use", "unit": "Percent"} ], "metrics_collection_interval": 60 }, "LogicalDisk": { "measurement": [ {"name": "% Free Space", "unit": "Percent"} ], "metrics_collection_interval": 60, "resources": ["*"] } }, "append_dimensions": { "InstanceId": "${aws:InstanceId}", "InstanceType": "${aws:InstanceType}" } } } '@ # 設定ファイルの保存 [System.IO.File]::WriteAllText("C:\ProgramData\Amazon\AmazonCloudWatchAgent\Configs\Config.json", $configJson) # CloudWatch Agentの起動と設定 & "C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1" -a fetch-config -m ec2 -s -c file:"C:\ProgramData\Amazon\AmazonCloudWatchAgent\Configs\Config.json" Start-Sleep -Seconds 10 & "C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1" -a start # エージェントのステータス確認とログ出力 & "C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1" -a status | Out-File -FilePath "C:\CloudWatchAgent\agent-status.txt" # スクリプトディレクトリの作成 New-Item -ItemType Directory -Force -Path "C:\infra\script" # S3転送スクリプトの作成 $s3TransferScript = @' # 日付とホスト情報定義 $hostName = [System.Net.Dns]::GetHostName() $date = (Get-Date).AddDays(-1).ToString("yyyyMMddHHmmss") $zipFileName = "任意の名前" -f $hostName, $date # S3のバケット名とプレフィックス $bucketName = $args[0] $prefix = "任意のプレフィックス" -f $hostName # 抽出対象イベントログの名前定義 $eventLogNames = "System", "Application", "Security" # スクリプト名定義 $scriptName = $MyInvocation.MyCommand.Name # イベントソースが存在するかどうかを確認する if (-not [System.Diagnostics.EventLog]::SourceExists($scriptName)) { # イベントソースが存在しない場合、新しく作成する New-EventLog -LogName Application -Source $scriptName } # スクリプトの開始ログを出力する Write-EventLog -LogName Application -Source $scriptName -EntryType Information -EventId 100 -Message "[Info 001]: Script started." # イベントログをエクスポートしてzip化処理 ForEach ($logName in $eventLogNames) { Try { $fileName = "{0}-{1}.txt" -f $logName, $date Get-WinEvent -FilterHashtable @{ LogName=$logName; StartTime=(Get-Date).AddDays(-1).Date; EndTime=(Get-Date).Date } | Format-Table -AutoSize -Wrap > $fileName Compress-Archive -Path $fileName -Update -DestinationPath $zipFileName Remove-Item $fileName } Catch { $errorMsg = "[Error 001]: Script failed while exporting and zipping event logs. Error details: $_" Write-Error $errorMsg Write-EventLog -LogName Application -Source $scriptName -EntryType Error -EventId 1 -Message $errorMsg Break } Finally { Write-EventLog -LogName Application -Source $scriptName -EntryType Information -EventId 101 -Message "[Info 002]: Exporting and zipping event logs completed." } } # AWS S3にZIPファイルをアップロード Try { Write-S3Object -BucketName $bucketName -File $zipFileName -Key $prefix/$zipFileName } Catch { $errorMsg = "[Error 002]: Script failed while uploading the ZIP file to S3. Error details: $_" Write-Error $errorMsg Write-EventLog -LogName Application -Source $scriptName -EntryType Error -EventId 2 -Message $errorMsg } Finally { Write-EventLog -LogName Application -Source $scriptName -EntryType Information -EventId 102 -Message "[Info 003]: Uploading the ZIP file to S3 completed." Remove-Item $zipFileName } Write-Host "ZIP file has been uploaded to S3." Write-EventLog -LogName Application -Source $scriptName -EntryType Information -EventId 103 -Message "[Info 004]: Script completed." '@ # スクリプトの保存 [System.IO.File]::WriteAllText("C:\infra\script\s3_log_transfer.ps1", $s3TransferScript) # タスクスケジューラーの設定 $action = New-ScheduledTaskAction ` -Execute "PowerShell.exe" ` -Argument "-ExecutionPolicy Bypass C:\infra\script\s3_log_transfer.ps1 アップロード先S3バケット名" $trigger = New-ScheduledTaskTrigger -Daily -At 2am $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable -DontStopIfGoingOnBatteries -AllowStartIfOnBatteries Register-ScheduledTask ` -TaskName "S3EventLogTransfer" ` -Action $action ` -Trigger $trigger ` -Settings $settings ` -User "System" ` -RunLevel Highest ` -Force # AWS Tools for PowerShellのインストール Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force Install-Module -Name AWS.Tools.Common -Force Install-Module -Name AWS.Tools.S3 -Force 周辺環境のデプロイが手間なので、今回私はAWS CDKでデプロイしますが、EC2作成時にユーザーデータ欄に以下のように<powershell></powershell>と挟んでスクリプトをコピペしてください。 動作確認 まずは、CloudWatchLogsからです、SYSTEMログとSECURITYログは割愛しますが、以下のようにデプロイ直後から出力されています。           続いて、イベントログS3アップロードです。 以下のようにEC2のタスクスケジューラにタスクがしっかり登録されていました。 では、強制的に実行してみましょう。 以下のようにイベントログ(Application)に途中経過が出力されます。 S3にログがアップロードされていることを確認できました。 今回は以上となります。 少しでも皆様のお力になれれば幸いです。 次回はAWS CDK周りの案件に合わせた実装の記事を執筆したいと思います。
アバター
みなさん、こんにちは!SCSK 池田です。 HAクラスタ製品である「LifeKeeper」ですが、何かあった場合の保険の意味合いが強いだけに、フェイルオーバが起きてしまった場合のサポートレベルはとても気になるところですよね。 今回は、そんな「LifeKeeper」のサポートの種類について解説したいと思います。 LifeKeeperのサポートにはいろいろな種類があります 一般的に「サポートの種類」と聞いてパッと思い浮かぶものとして、「平日日中サポート」と「24時間365日サポート」が挙げられると思います。「LifeKeeper」の場合も同じように「平日日中サポート」と「24時間365日サポート」がありますが、特に24時間365日サポートにはいくつかのバリエーションがあり、少々解り辛いところがあります。 LifeKeeperのサポート種類 ● 標準サポート ・・・平日日中サポート(平日 9時~17時半)と呼ばれるもの ● Premiumサポート ・・・24時間365日サポート ※シビリティ1に該当する場合の障害復旧支援 ● 拡張Premiumサポート ・・・24時間365日サポート ※シビリティ1もしくはシビリティ2に該当する場合の障害復旧支援 ● 拡張Premium++サポート ・・・24時間365日サポート ※拡張Premiumサポートに、4時間以内の回答をSLAとして付け加えた障害復旧支援 メンテナンス期間が終了したLifeKeeper製品バージョンであっても、メンテナンスサポートの範囲でサポートサービスを提供 ご覧のように24時間365日サポートには、3種類のレベルの異なるサポートがあります。下にいくほどサポートレベルが手厚くなるのが特徴です。 シビリティとは? 先述の説明に書かれている「 シビリティ 」ってなんだろうと思われたかたも多いと思います。 シビリティ とは、 重大度 を示す指標のことです。 シビリティの 数値が小さい方が「重大度が高い」 と捉えていただければと思います。 サイオステクノロジー社の定義するシビリティは以下のようになります。 シビリティ1 ・・・LifeKeeperにより保護され正常稼動していたシステムおよびサービスにおいて、 LifeKeeperで定義したリソースが正常に起動できないために、アプリケーションがサービスを提供できない状態を指します。          シビリティ2 ・・・お客様のシステムが提供するサービスは維持されていながらも、その能力が大幅に低下している状態を指します。 またLifeKeeperが提供する機能に大幅な制限が加わっている状態も含みます。 ちょっと堅苦しいので、もう少し実例を交えてご説明すると、 シビリティ1 ・・・本番稼働中のシステムで、何らかの問題が発生したもののフェイルオーバできず システムの提供ができない状態 ※但し計画メンテナンス中に発生した障害は除く          シビリティ2 ・・・本番稼働中のシステムで、何らかの問題が発生し、フェイルオーバの後にシステムの提供はできるものの、 可用性が 失われている状態 (1台のみでシステム提供している状態) となります。 これらの意味するところは何かというと、 24時間365日サポートは、重大な障害が発生している時にのみ利用できる 逆をいうと、 障害が発生していないときは平日日中のサポートレベルになる ということです。 この点は抑えておいていただきたポイントとなります。 LifeKeeper製品サポート内容 表にまとめるとこんな感じになります。   標準サポート Premiumサポート 拡張Premiumサポート 拡張Premium++サポート メール対応 平日9:00~17:30 土日祝祭日年末年始を除く ● ● ● ● 電話対応 (フリーダイアル) 24時間365日 × ● シビリティ1 ● シビリティ1 シビリティ2 ● シビリティ1 シビリティ2 4時間以内返信 (平日9:00~17:30) × × × ● ライフサイクル延長 (Ver制限あり) (※) (※) (※) ● ライフサイクル超延長 (Ver制限なし)  ×  ×  × ● (※)拡張Premium++サポートのみライフサイクル延長が付属しています。それ以外のサポートを購入している場合は、別途、延長サポートを購入いただければライフサイクル延長ができます。   まとめ 今回は、LifeKeeperのサポートの種類について解説しました。お客様の求めるRTO(目標復旧時間)に見合ったサポートレベルを適切に選択するにあたって、本記事を参考にしていただければと思います。 最後に纏めます ・LifeKeeperには、4つのサポートの種類がある ・シビリティという考え方がある ・シビリティレベルによっては、24時間365日のサービスが受けられないことがあるので注意が必要 ・最上位(拡張Premium++サポート)では、問い合わせから4時間以内の回答というサポートレベルが付加される
アバター
SCSKの畑です。 前回エントリの後編として今回はバックエンド側のサービスを対象に解説します。 前回の記事はこちら サーバレスアーキテクチャにおける Web アプリケーションの実装事例(前編) 案件事例に基づく、サーバレスアーキテクチャにおける Web アプリケーションの実装の概要について2回に分けて説明します。前編はフロントエンド側です。 blog.usize-tech.com 2025.02.07 アーキテクチャ図 いつものやつです。図内に注釈もあるので、各サービスの役割は何となくご理解いただけるものかと思います。   バックエンド側のサービス 以下の項目がバックエンド側のサービスになります。Lambda/S3 についてはバックエンド側でも活用しているので両方に出てきます。また、Redshift については本アプリケーションでの管理対象という位置づけのため、本エントリでは直接的には触れません。Redshift に関するネタは幾つかありそうなので、またその際に。 AWS Amplify AWS AppSync Amazon Cognito Amazon DynamoDB AWS Lambda Amazon S3 なお、AppSync/Amplify/Cognito あたりは他のエントリでも色々な内容を取り上げていることもあり、重複するような内容は適宜割愛しています。このため、全般的に本アプリケーションにおけるサービスの使用理由や所感などが中心の内容となっており、前編とは若干様相が異なりますがご了承ください。(詳細な内容に踏み込むと分量が多くなってしまい、バランスが悪くなるので・・)   AWS Amplify これまでのエントリで何回もメイントピックとして取り上げていますが、具体的な構成管理対象は10回目のエントリに記載した通り AppSync と DynamoDB の2つです。実質的にはほぼ GraphQL Transformer を使って AppSync を構成・デプロイするためだけに使用したと言ってよく、その用途だと自然にこの2つが対象になりました。Lambda や Cognito を管理対象としていないのも同エントリの通り、細かい設定ができない&お客さん環境で Amplify を使用できないためです。 正直なところ、今回のような使用方法だと、GraphQL Transformer なり codegen で Javascript/Typescript 用のクライアント SDK を生成する機能がローカルから使用できれば十分だったのですが、調べた限りはそのように使用できそうにはありませんでした。普通は CI/CD 機能までセットで使用することになるというか、それをメリットと感じて使用するケースが多いと思うので、上記のように使いたいというモチベーション自体が珍しいのだとは思いますが・・   AWS AppSync こちらに至ってはほぼ毎回のエントリで何かしら取り上げていますが、一部ビジネスロジックを含むアプリケーションのバックエンド処理をほぼ全て任せるような使い方をしています。概要図の通り、DynamoDB は 一部処理を除いて(Amplify によって構成した)AppSync のリゾルバにより直接やり取りしていますが、それ以外のサービス(S3/Redshift)については全て Lambda 経由でやり取りしています。 理由は単純で、AppSync が対応していないデータソースであり、自前でそれらの HTTP エンドポイントとやり取りするようなリゾルバを実装するのは、開発時点でのスキルやコストを鑑みるとハードルが高いと感じたためです。今振り返っても、Lambda 上で実装している処理の内容的に、AppSync のリゾルバ側に移管できる内容は数割程度かなと思います。例えば、Cognito からユーザ/グループ情報を取得してくるような処理などは実装できると思いますが、Redshift とのデータやり取りになってくると Lambda レイヤー経由で様々なライブラリを使用していたりするので、おそらく実装は無理だろうなと。機能的に AppSync JS がもっと充足してくればあるいはという感じでしょうか。 リゾルバーおよび関数の AWS AppSync JavaScript ランタイム機能 - AWS AppSync AWS AppSync の JavaScript リゾルバーユーティリティヘルパーについて説明します。 docs.aws.amazon.com というか、RDS に対応してるなら Redshift にも対応してくれてもいいのにと思わなくもない・・のですが、DWH (Redshift) とのやり取りとなると一般論としてデータ量が大きくなることが想定されることを考えると、AppSync の特徴や用途に適さないために対応していないということなのかなと。。   Amazon Cognito 本アプリケーションのユーザ/グループを管理するために使用しています。詳細は 2回目のエントリ で説明していますが、本アプリケーションを使用するためには Cognito によるユーザ認証・認可が必要であり、ユーザプールに紐付けた ID プールの「認証されたアクセス」経由で付与される IAM ロールの権限を以ってアプリケーションを使用します。 こちらは正直あまり書くことがないので余談寄りの話題になりますが、当初はユーザ/グループのメンテナンスに際してアプリケーション側に管理画面を作る想定はありませんでした。ただ、思ったより AWS マネジメントコンソールの画面が使いづらいところがあり、手順に落としてもやや冗長な内容になってしまうことから、お客さんからの要望もあってアプリケーション側で管理画面を作ることになりました。設定手順自体はさておき、運用管理を考えるとユーザ一覧における任意項目でのソートとか、ユーザ一覧のエクスポートくらいはできても良いんじゃないかと思ったりします。(検索はできますが・・)   Amazon DynamoDB アプリケーション用のデータベースとして使用しています。概要図にも記載がありますが、具体的な用途としては以下3つです。前者2つの用途は、本アプリケーションにおけるメンテナンス対象の Redshift テーブル、及び実行対象の ETL/ELT ジョブネット(ステートマシン)をターゲットとしています。 セッション/ステータス管理 オペレーションログ出力 アプリケーションマスタ(設定) 排他制御に関するエントリでも少し言及した通り、DynamoDB 自体を積極的に採用したというよりは、Amplify/AppSync と連携して容易に開発ができ、かつ一般的に RDBMS で備えているような機能性を持つサーバレスサービスである、という特徴から選んだような感じです。もちろん DynamoDB は本質的に KVS (Key Value Store) であり、Oracle や PostgreSQL などの RDBMS とは色々な相違点がありますが、上記のような用途においては KVS で十分でした。 最も今振り返ると、結果的にそうだった部分もあるのは否めないところです。特にテーブルの論理設計については、広野さん執筆の以下エントリなどを事前に読んでおくべきだったかもしれません。このあたりは開発時の経緯などもあるのですが、実装しながら設計を拡張していけるのが KVS/スキーマレスの良いところでも悪いところでもあると実感できました。幸いにも、本アプリケーションの実装においては良いところを享受できた割合の方が大きかったと思っています。 Amazon DynamoDB のテーブル設計で悩んだら最初に読もう -これだけ知ればある程度の検索には対応できる- Amazon DynamoDB のテーブルは構築前の設計が重要です。本記事では、設計するにあたり知っておくべき検索仕様を紹介します。 blog.usize-tech.com 2022.07.05 一方、初めて本格的に扱ったサービスであるということもありちょこちょこ躓いた点もあったため、以下にまとめてみました。本当に大した内容ではないというか、本当に初学者のような内容ですが・・ パーティションキーの定義変更は不可能であり、変更するためにはテーブルの再作成が必要なこと パーティションキーに指定している列の名前を変更したかったのですが、それもパーティションキーの定義に当然ながら含まれるということで再作成が必要となりました。今考えると DynamoDB のテーブル作成時にパーティションキーを指定する必要がある時点で、何となくそういう仕様になっていることは察せられた気もします。 1項目あたりの最大データ量が 400KB であること 実装最初期はメンテナンス対象のテーブルデータ自体を DynamoDB の項目として保持するような設計としていたのですが、この制限に引っかかったため断念しました。今振り返るとあまり筋の良い設計ではなかったので、早々に方針を転換できたことは良かったと思っています。仮に数 MB 程度だった場合はそのまま進めていたかもしれません・・   AWS Lambda AppSync の項目で記載した通り、主に Redshift/Cognito とのやり取りする機能の開発に使用しています。ランタイムは実装コストを重視して慣れている Python としました。特に Redshift とのやり取りにおいて Pandas ライブラリを使用したかったというのも理由の一つです。 詳細な内容については Lamdba ごとの各論になってしまう部分がありますが、今回の構成のように AppSync のデータソースとしての用途では思ったより大分扱いやすかったです。AppSync からの入力がどのように event に入ってくるかを調べるのが少し手間だった程度で、出力については GraphQL のスキーマ定義通りに入れてあげればそのまま AppSync 側で受け取ってくれるのでラクでした。Lambda 側での例外発生時も、例外をそのまま AppSync に渡すだけであれば特別な工夫は不要でした。(Lambda から例外を raise すれば、それをそのままフロントエンド側にも渡してくれる) 逆に、Lambda をオンライン機能のバックエンド処理用として扱う場合によく問題として挙げられる、コールドスタート発生時のレスポンス悪化も実感したところです。本アプリケーションの用途を鑑みると大きな問題ではありませんが、回避策が実質的な常時起動 (Provisioned Concurrency) となってしまうのはサーバレスの思想/メリットから遠ざかってしまうという点で悩ましいですね。。 関数に対するプロビジョニングされた同時実行数の設定 - AWS Lambda Lambda での 同時実行 は、関数が現在処理している未完了のリクエストの数です。利用できる同時実行コントロールには、次の 2 種類があります。 docs.aws.amazon.com もし別案件で Amplify を使用しない方針とした場合は、ダイレクト Lambda リゾルバについても試してみたいところです。   Amazon S3 バックエンド側では、Redshift ⇔ アプリケーション間のテーブルデータのやり取りにおけるデータの(一時)保管場所として使用しています。つまり、実質的にアプリケーションが読み書きするのは S3 上のデータとなり、 7回目のエントリ でも触れたように AppSync/Lambda を通してアプリケーション ⇔ S3 ⇔ Redshift 間でデータのやり取りをするようなアーキテクチャとなっています。 当初は S3 を間に挟む予定はなかったのですが、以下の理由によりこのような構成としました。 前編で記載した以下のアプリケーション機能を実装するにあたり、テーブルデータを保持しておく場所が必要だったため アプリケーションのメンテナンス対象テーブルの(データ)バージョン管理機能 アプリケーション経由でテーブルデータを更新する際の簡易ワークフロー機能 Redshift のテーブルデータを COPY 文で更新するにあたり(厳密には truncate -> insert)、COPY 対象のデータを S3  などの外部データストアに配置する必要があったため https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/r_COPY.html#r_COPY-syntax-overview-data-source もちろん、上記理由のみだと他の選択肢も取れたのですが、全体としての扱いやすさやお客さん環境での作成におけるハードルの低さも鑑みて S3 を使用することにしました。結論としては良い選択ができたと思っています。 以降、テーブルデータをどう保持しているかや、どのような設計思想でメンテナンス機能を実装したのかをつらつら書いていたのですが、思った以上に分量が多くなってしまいそうだったので、こちらの内容もまとめて別エントリのネタにさせていただこうと思います。。   まとめ バックエンド側の話は別エントリのネタとして適宜消化していることもあり、そんなに書けることないかなと思っていたのですが思っていた以上に捻り出せました。アーキテクチャとしては最初からある程度固まっていたように思えていたのですが、振り返ってみると色々あったなあというのが正直な感想です。 本記事がどなたかの役に立てば幸いです。
アバター