TECH PLAY

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

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

1234

LifeKeeper記事では、前々回DRBD×LifeKeeperの組み合わせの製品と性能についてご紹介しました。 第10回 DRBD × LifeKeeperの高可用性リアルタイムレプリケーションを探る – TechHarmony   今回の記事では、DRBD×LifeKeeper製品であるDisaster Recovery Add-onの構築方法そして機能の検証をしていきたいと思います!   検証環境について 今回、Disaster Recovery Add-onの機能を確認する環境として AWS上の東京リージョンに2台、大阪リージョンに1台の計3ノードによる マルチリージョンでの高可用性構成にてDR環境を構築し、機能の検証を行っていきます。 以下 AWS での3ノード構成では、通常時の想定として 東京リージョンをメインサイトとして、東京1号機、東京2号機 が動作し、 大阪リージョンをバックアップサイトとして、大阪1号機が動作をしている想定の構成としております。 環境の設定値、ルーティング設定などは以下ブログに詳細を掲載しておりますので、気になる方はご参照下さい。 AWSマルチリージョンにおける高可用性方式を実装してみる – TechHarmony   LifeKeeperインストール/DRBD設定手順 DR環境でのLifeKeeperの設定手順について解説していきます。 まずは、LifeKeeperのインストールする際の手順となります。 LifeKeeperをインストールするタイミングでDisaster Recovery Add-onの機能を有するオプションを一緒にインストールすることが可能です。 インストール時以下のように、ARKと呼ばれるミドルウェア選択項目にて「DRBD Recovery Kit」を選択すればOKです。 インストール時の注意点として、「Quorum/Witness」の選択を忘れずにしましょう。 LifeKeeperが持つQuorum/Witness機能を使用することで、複数ノードが同時にActive状態になることを防止できます。   インストールが完了しましたら、 DRBDの設定作業を行っていくためのGUIをインストールする作業を行います。 設定に関しては、LifeKeeper GUIにて実行できますので、その事前準備を行います。 GUIはLKWMC[LifeKeeper Web Management Console]と呼ばれるWebアプリケーションを利用していきます。 LKWMCのインストールファイルを各ノードに配置し、インストールスクリプトを実行することで利用することができます。 LKWMC利用の注意点として、TCPポート5110を使用するため、通信許可の設定が必要です。   GUIの準備ができましたら、DRBDの設定を投入していきます。 設定内容は以下の5項目となります。 1 コミュニケーションパス 2 DRBDリソース作成/拡張 3 IPリソース作成/拡張 4 Generic ARK作成/拡張 5 Quorum設定   ■コミュニケーションパス LifeKeeper では、複数台のノードをお互いに接続することで、クラスターを構成していきます。 そのため、各ノード間で通信を行うための経路を事前に設定する必要があります。 この通信経路のことを LifeKeeper では「コミュニケーションパス」と呼び、こちらの設定を行います。 コミュニケーションパス>オペレーション にて各ノードの設定を入れていきます。作成が完了すると上記画像のような表記がされます。 コミュニケーションパスを作成する際の注意点なのですが、名前解決とTCPポートの穴あけが必要となります。 今回の環境では、/etc/hostsに各ノードの情報を記載し、コミュニケーションパスで使用する7365のポートの通信許可の設定を行いました。   ■DRBDリソース作成/拡張 コミュニケーションパスの作成が完了できましたら、次はDRBDリソースの作成と各ノードに拡張をしていく作業となります。 DRBDリソースは、共有ストレージを使用せずに可用性の高いクラスターを構築する機能を提供します。 まず各ノードにて、マウントポイントの対象となるデバイスの確認(ない場合は作成)、 対象デバイスにてパーティションの作成を行います。 上記作成ができましたら、GUIにてリソース作成を行っていきます。 リソースツリー>オペレーションからDRBDリソース作成を行えます。   作成が完了しますと、上記のように「drbd-mp」というマウントポイントの作成ができます。 このマウントポイントを各ノードへ拡張を行うと、以下のようにデータの同期先として利用できるようになります。   リソース作成/拡張の設定を投入する際に、切り替え/切り戻し動作の設定を行うことができます。 切り替えを手動 or 自動で行うのか。 切り戻しを手動 or 自動で行うのかを選択することが可能です。 今回の設定では切り替えを自動、切り戻しを手動の設定にて行いました。   ■IPリソース作成 続いてIPリソースの作成を行います。 IPリソースは各ノード間で切り替えることができる仮想IPアドレスの作成を行います。 今回は、「20.1.1.1」という仮想IPアドレスを用意し、設定していきます。   AWS上での仮想IPアドレスについては過去に解説記事を投稿していますので、こちらをご参照ください。 【LifeKeeper】AWSでは仮想IPアドレスが使えない!?をこうして解決する!! – TechHarmony   ■GenericARK作成/拡張 メインサイトである東京リージョンがDownした際に、自動で大阪リージョンへルートテーブルが切り替わるためのスクリプトを組み込みます。 詳細については別記事にて紹介予定となります。   ■Quorum設定 今回は自動切り替わりの動作とするため、Quorum設定を行います。 (手動切り替えの際は設定不要となります) GUI上での設定対応が終わりましたら、Quorum機能を有効にするためmajorityからstorageへ変更、 本番/災対サイト以外のリージョンにS3の作成を行い、その情報を設定へ追記します。 Disaster Recovery 構成ではメインサイトの2台が停止する想定のため、バックアップサイトのノード1台では Quorum を持つことができず、自動起動ができなくなります。 この場合、storage モードを使用することでメインサイトの2台が停止しても、バックアップサイトのノードにフェイルオーバーして、サービスをすばやく継続することができます。 storage としては、メインサイト/バックアップサイトとは別のリージョンに Amazon S3 を準備しておきます。Quorum設定なしでも自動で起動しますが、ネットワークが分断した場合(メインサイトは生きているが、クラスタノード間のネットワークが切断)はスプリットブレインになる可能性もあるので、Quorum/Witness の使用を推奨としています。   これにてLifeKeeperのインストール及びDRBD設定が完了となります。   シナリオ/機能検証 設定が完了したところで、Disaster Recovery Add-onの機能を検証していきたいと思います。 今回の確認観点としては、 ●フェイルオーバー時の動作 東京リージョンが使用不可になった際、大阪リージョンへのフェイルオーバーが問題なく行われるか。 ●データレプリケーションの整合性 DRBDリソースの作成時に指定したマウントポイントである”drbd-mp”が ファイルシステムとして稼働しているか、対象のファイルがレプリケーションされているか。 この2つの観点で機能を検証してみます。 テストシナリオとして、東京1、2号機(東京リージョン)をDownさせ、大阪1号機へフェイルオーバーを行います。 まず、通常時として以下のような状態となります。 東京1号機がActive、東京2号機/大阪1号機がStandbyの状態となります。 東京1号機に「drbd-mp」が存在し、test.txtがあります。東京2号機/大阪1号機にはありません。   今回のシナリオに沿って東京リージョンの1,2号機をDownさせていきます。 以下画像が東京東京1,2号機が落ちている状態となります。 GUIでリソースの状態を確認してみると無事フェイルオーバーされ、大阪1号機がPrimaryの状態となりました。 レプリケーションされているか確認したところ、drbd-mp(マウントポイント)が移動されており、 対象ファイルも確認できました。 切り替わり時間としては、東京リージョンをDownさせてから体感40~50秒ほどで切り替わりました。   東京1,2号機を復旧させると、大阪1号機がActiveで稼働している状態となります。 復旧後の切り戻しは手動 or 自動のどちらかを指定して戻すことができますが、 今回の切り戻し設定は、切り戻しのタイミングを管理者側のタイミングで復旧できるよう手動としておりますので、 東京が復旧してきても大阪1号機がActiveの状態のままとなります。   まとめ 今回AWS環境でのLifeKeeperを用いた災害対策としてDisaster Recovery Add-on の構築、機能検証を行い、 異なるリージョン間のデータレプリケーションの確認を行いました。 マルチAZ構成での可用性を高めるだけでなく、マルチリージョン構成をとることで、 遠隔地サイトへのスタンバイノードに対しても高速なレプリケーションと、障害発生時のフェールオーバーを可能とするため、自然災害によるシステム停止から素早くアプリケーションを回復することが可能となり、 よりシステムの信頼性と可用性を向上させ、企業のIT運用をさらに強固なものにすることができるなと感じました。 近年の災害対策としてぜひDisaster Recovery Add-onをご活用いただければと思います。
本記事は 新人ブログマラソン2024 の記事です 。 こんにちは。2024年度入社の野上です。 以前、MySQLの初心者ながらレプリケーション方式をまとめた記事を投稿させていただきました。 今回は、以前まとめた方式の中で一般的とされている「非同期レプリケーション」を構築してみました。 これは実際に私が携わった案件で経験した内容になります。 非同期レプリケーションの概要をわかっていても、実際に構築するとなると考慮しなければいけない事が多々ありました。 ブログや公式ドキュメントで書かれていない内容もありましたので、自分の知識のアウトプットもかねて皆さんにご紹介いたします。 非同期レプリケーションとは まず非同期レプリケーションとはどういう方式なのかという詳細に関しては、前回私が書いた記事を見ていただきたいです。 MySQL レプリケーションの方式をまとめてみた – TechHarmony ここで簡単に説明しますと、ソースサーバ(メインで使用するDBサーバ)でデータを更新する処理と、レプリカサーバ(複製されたDBサーバ)にデータの更新を反映させる処理が、非同期で行われます。 データベースのデータを更新するときには、トランザクション(データベースの操作を行う1つの処理単位)のコミットを実行し、コミットが完了することで、更新を確定させます。 非同期レプリケーションではレプリカサーバでの処理❶~❷の完了を待たずにコミットを完了します。   実際に構築してみた 非同期レプリケーションを構築する順序は以下の通りになります。 サーバの準備 データベースのコピー パラメータ設定 レプリケーション用ユーザーの作成 レプリケーション設定 各順序を説明しながら、レプリケーションを構築していきます。 サーバの準備 レプリケーションを構築するにあたり、レプリケーションを張る2つのサーバが必要となります。 Amazon EC2を用いて検証用のサーバを構築しました。 今回はMySQLのバージョンは 8.0.36 を使用しています。 MySQLはバージョンの違いによりコマンドが異なりますのでご注意ください 。 用途 ホストIPアドレス MySQLバージョン ソースサーバ 10.10.23.187 MySQL8.0.36 レプリカサーバ 10.10.23.19 MySQL8.0.36   データベースのコピー 対象のサーバを準備したら、ソースのデータベースをレプリカにコピーする必要があります。 ただレプリケーションを張るだけでは、レプリカのデータベースはソースと同じにはなりません。 レプリケーションは、ソースのバイナリログの内容をレプリカに転送するため、 バイナリログが残っている部分しかレプリケーションされません 。バイナリログの保持期間は、 「binlog_expire_logs_seconds」 というパラメータで設定されているため、my.cnfというパラメータの設定ファイルの内容を確認することをお勧めします。 データをコピーする方法は2通りあり、どちらかの方法でコピーを行います。 dmpファイルを用いてコピーする(MySQLの公式ドキュメントに記載されている) MySQLのデータディレクトリをコピーする dmpファイルを用いた方法が一般的ですが、今回は案件の中で私が勉強したことを共有したいこともあり、MySQLのデータディレクトリをコピーする方法で行います。 ①ソースでMySQLのデータディレクトリのパスを確認する データディレクトリのパスは、my.cnfに記述されているため以下のコマンドを実行します。     ②データディレクトリを圧縮する 以下のコマンドを実行することで、「datacopy.tar.gz」という圧縮ファイルが生成されます。     ③生成した圧縮ファイルをレプリカに送信する ファイルの送信方法もいくつかありますが、今回は2つのサーバで直接通信が可能なので、scpコマンドを利用してファイルの送信を行いました。     ④レプリカ側で圧縮したファイルを解凍してデータディレクトリを上書きする 以下のコマンドを実行することでデータディレクトリのコピーが完了します。 ※ここではmvコマンドにより元のデータディレクトリを退避させることで、安全にコマンドを実行しています。     ⑤auto.cnf の削除 以下のデータディレクトリ内に含まれる「auto.cnf」という名前のファイルの削除を行い、MySQLを再起動します。(※)       (※)auto.cnf とは、MySQL server のUUIDを格納したファイルです。 UUIDとは一意の識別子であり、UUIDが重複した状態ではレプリケーションを張ることができません 。そのため、ソースとレプリカで異なるUUIDを使用する必要があります。auto.cnf は自動で生成されるファイルであり、手動で削除してMySQLを再起動を実行することで自動作成されます。⑤の手順を行うことで、 ソースとレプリカで異なるUUIDとなるため、レプリケーションを張ることが可能になります 。 以上の手順により、データディレクトリのコピーが完了しました。   パラメータ設定 レプリケーションを張るためには、レプリケーションに必要なパラメータ設定をする必要があります。 MySQLのパラメータは「my.cnf」という設定ファイルに記述してあり、そのファイル内のパラメータ値を変更します。   ① 設定が必要なパラメータを以下の通りに設定する <ソースとレプリカ両方に設定> gtid_mode = ON GTID(グローバルトランザクションID)を有効化するパラメータです。 GTIDを有効化することによりソースとレプリカの一貫性の判断を容易にします。 enforce_gtid_consistency = ON GTIDを使用する際に、整合性に違反するトランザクションを禁止する設定です。 server_id = 1(ソース), 2(レプリカ) レプリケーションの構成内でソースとレプリカを一意に識別するために用います。 <レプリカのみに設定> read_only = ON レプリカ側でデータの更新を拒否します。 SUPER権限を持つアカウントは拒否しません。 super_read_only = ON レプリカ側でSUPER権限を持つアカウントからの更新を拒否します。   ② MySQLを再起動する my.cnf の内容を変更したときには、MySQLを再起動することで設定を反映することができます。 再起動には以下のコマンドを実行します。   以上の手順を実行することでMySQLのパラメータ変更が完了しました。   レプリケーション用ユーザーの作成 次に、レプリケーションを行うために必要なMySQLのユーザーを作成します。 レプリケーションを張る際には、レプリカがソースのMySQLユーザーとしてデータにアクセスします。そのため、ソース側にレプリケーションのユーザー権限を持ち、レプリカのIPアドレスからのログインを許可するユーザーが必要です。 ①ソース側でMySQLにログインし、以下のステートメントを実行してユーザーを作成する     ここでは、replica@10.10.23.19 というユーザーを作成しています。 MySQLではユーザー名とホスト名の組み合わせによってユーザーを作成します。   ②作成したユーザーにレプリケーション権限を与える 以下のステートメントを実行します。作成したユーザーがレプリケーション権限を持っていることが確認できます。         以上の手順でレプリケーション用のユーザーの作成が完了しました。   レプリケーション設定 パラメータの設定が完了したら、いよいよレプリケーションを張ります。 ①レプリカ側でMySQLにログインして、レプリケーションの設定を行う 以下のステートメントを実行します。       ここでは、先ほどソースで作成したユーザーのホストアドレス、ユーザー名、パスワードを指定します。 さらに、「source_auto_position」,「source_ssl」という2つのオプションを付けています。 「source_auto_position」はGTIDを使用するために必須のオプションです。 「source_ssl」 はレプリケーションの通信がSSL接続するというオプションです。(※) (※) MySQLはバージョン5.7以前と8.0以降でユーザー認証の方式が変更されています 。5.7以前はデフォルトの認証プラグインが「mysql_native_password」ですが、8.0以降は「caching_sha2_password」となっています。それにより、 セキュアな接続が必須 となりました。そのため 「source_ssl」のオプションを付けない場合にレプリケーション接続が失敗してしまいます 。 (参考) https://dev.mysql.com/doc/refman/8.0/ja/upgrading-from-previous-series.html#upgrade-caching-sha2-password   ②レプリケーションの開始 以下のステートメントを実行することでレプリケーション接続を開始します。     ③レプリケーションのステータスの確認 以下のステートメントを実行することでレプリケーションのステータスを表示します。                                             実行結果の赤枠で囲んだ項目は以下を意味します。 Replica_IO_Running=Yes ソースのバイナリログを読み込み、レプリカにログを転送するスレッドが動いていることを示します。 Replica_SQL_Running=Yes レプリカで、ソースから転送されたログからデータの更新を行うスレッドが動いていることを示します。 Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error:        エラーが発生していないことを示します。 上記のことから、 実行結果通りであればレプリケーション接続が成功 していることになります。 以上の手順を実行しレプリケーションの構築に成功しました。MySQLでは非同期レプリケーションがデフォルトであるため、非同期レプリケーションの構築ができたことになります。 まとめ 本記事では、非同期レプリケーションを実際に構築してみました。 私が案件の中で手を詰まらせた項目は紹介できたと思っています。 しかし、レプリケーションは要件によってパラメータの値などを変化させる必要があります。 そのため今回紹介したのはレプリケーションの構築の1つの例ですが、少しでも読んでくださった方の助けになるポイントがあれば嬉しいです。
前回、AWS Glue と Amazon Athena でS3上のデータを読み取ることができました。 Amazon Athena + AWS Glue で Amazon S3 上のデータを読み取る – TechHarmony 今回は Amazon Athena 上のデータを Amazon QuickSight で可視化したいと思います。 QuickSight の詳細については QuickSight公式ページ をご参照ください。   やってみた Amazon QuickSight AWSマネジメントコンソールからQuickSight画面を開きます。 初めてQuickSightを使用する際はアカウントの設定画面が開きますので、適宜設定してください。 「新しい分析」をクリックします。   「新しいデータセット」をクリックします。   データソースを選択します。今回はAthenaを選択します。   データソース名を入力し、「データソースを作成」をクリックします。 。   可視化したいデータがあるデータベースおよびテーブルを選択し、「選択」をクリックします。   「Visualize」をクリックします。   以上で、インポートが完了です。 自動で分析の画面に移ります。   最初にグラフが1つ用意されているので、フィールドリストから必要なものをドラッグ&ドロップで追加します。 X軸、Y軸に分析対象のデータを配置し、 分析対象のデータ形式に応じて、可視化のフォーマットもQuickSight側で色々準備されています。 今回は試しに積み上げ面折れ線グラフと円グラフでデータを可視化してみました。   おわりに Amazon S3 上のデータを Amazon Athena と Amazon QuickSight で可視化することができました。 今回は単純なデータでしたが、大まかに使い方を理解することができました。 サーバレスサービスなので手軽に利用開始でき、初心者でも使いやすそうだなという所感です。 データ分析をやってみたいけど難しそうだな、、、と思っている方に少しでもイメージが伝われば幸いです。
こんにちは。SCSK株式会社の上田です。 2024年12月10日に、ポイントリリースバージョンである Zabbix 7.2 がリリースされ、Zabbix7.0 LTSには無かった新機能が追加されました! 今回は、追加された新機能の中から、 役に立ちそうな機能を4個、ピックアップしてご紹介します! 前回リリースされたZabbix7.0 LTSの新機能については、こちらの記事をご参照ください。 Zabbix 7.0で追加された便利な新機能10選 Zabbix 7.0では様々な新機能が追加されました。その中から便利な機能を厳選してご紹介します。 blog.usize-tech.com 2024.07.05   新機能の紹介 それでは、新機能を紹介していきます。 ①新しいウィジェット Zabbix7.0でも新しいウィジェットが追加されましたが、今回も 新しいウィジェットがいくつかリリースされました 。 1つ目は、 Host card 。選択したホストの情報を見ることができます。 Host Cardの詳細 表示する内容は、カスタマイズ可能です。 Host Cardで選択可能な項目 2つ目は、 Top items 。ホストのアイテムや、値やグラフで一覧表示できます。 Top itemsの表示内容 3つ目は、 Sparkline 。こちらはウィジェットの種類というより、ウィジェット上に表示できるグラフです。アイテムデータや、先ほどのTop itemsウィジェットで、スパークラインを表示することができます。 SparkLine(アイテムの値ウィジェット) SparkLine(Top itemsウィジェット) ②設定ファイルの環境変数サポート Zabbixサーバやエージェントなどの設定ファイルで、 環境変数 が利用できる ようになりました。これにより、設定値をハードコーディングする必要がなくなり、Dockerなどのコンテナ環境での設定が容易になりました。 ※Docker用であり、通常の運用での利用は推奨されていないようです。 ③NETCONFの対応 SSHアイテムがサブシステムパラメータをサポートするようになり、 NETCONF を利用したネットワークデバイスの監視が可能になりました 。これにより、従来のSNMPによる監視に加え、NETCONFの機能を活用した監視を実現できます。 先日のZabbixカンファレンスで、Zabbixの代表から「 8.0ではnetconfによるコンフィグ管理が可能になる 」という発言がありました。それの準備として実装されたのだと思います。 Zabbixでコンフィグ管理ができるようになれば、ネットワーク監視の幅が大きく広がるので、今後の動向に注目です。 ④新しいマクロ 新しいマクロ がリリースされ、監視設定とアラート設定がより柔軟になります。 以下は新しいマクロの例です。 {*TIMESTAMP}  マクロ:  イベントのUnixタイムスタンプを取得可能。 {FUNCTION.VALUE}  マクロ:  トリガー式内で個々の関数結果を参照可能。 これらのマクロを活用することで、 より高度な監視ロジックを構築する ことができます。 まとめ Zabbix 7.2の新機能を紹介しました。今回紹介した機能以外にも様々な機能が追加されています。詳細は公式ドキュメントをご参照ください。 Zabbix 7.2の新機能 Zabbix 7.2 introduces new ways to visualize your data and host information, and improves upon various existing monitorin... www.zabbix.com 「 Zabbix 7.2を新規にインストールしてみたい 」「 既存のZabbixからバージョンアップしたい 」という方は、是非弊社までお声がけください!! 最後まで読んでいただき、ありがとうございました。 弊社ではZabbix関連サービスを展開しています。以下ページもご参照ください。 ★Zabbixの基礎をまとめたeBookを公開しております!★ FAQ・お問い合わせ|SCSK Plus サポート for Zabbix 導入をご検討される際、よくあるご質問と回答についてまとめております。 www.scsk.jp ★SCSK Plus サポート for Zabbix★ SCSK Plus サポート for Zabbix 世界で最も人気のあるオープンソース統合監視ツール「Zabbix」の導入構築から運用保守までSCSKが強力にサポートします www.scsk.jp ★YouTubeに、SCSK Zabbixチャンネルを開設しました!★ SCSK Zabbixチャンネル 本チャンネルでは、SCSK株式会社でのZabbixに関するトレンド/事例紹介などを動画にまとめて取り上げております。最新のトピックについては、以下の弊社HPもしくはツイッターアカウントをぜひ参照ください。ツイッターアカウント: www.youtube.com ★X(旧Twitter)に、SCSK Zabbixアカウントを開設しました!★ x.com x.com
SCSKの畑です。10回目の投稿です。 今回は 6回目 のエントリで記載した、aws-amplify のSSR (Nuxt3)対応の詳細もとい補足について記載します。小ネタです。 対応の背景などは同エントリに記載しているのでここでは省略します。   aws-amplify 用のコンフィグファイル実装 aws-amplify モジュールを使用するにあたり、AppSync や Cognito など、モジュールが使用する各種サービスの情報が必要となります。言い換えると、Amplify.configure の引数としてどのような内容を設定するべきか、です。 ところが、具体的にどのように設定すべきなのかというドキュメントや情報が相対的に乏しく、あったとしても aws-amplify のバージョンが異なっておりコピペだと動かないなど、ちゃんと動かすまで結構苦労したため備忘として残しておこうと思います。例えば、GraphQL のデフォルト認証モードが IAM な場合は値を 「iam」に設定するみたいな情報とか、少なくとも実装時点ではちょっと調べた程度だと出てこなかったりしたんですよね。公式ドキュメントでは以下 URL が対応すると思うのですが、一覧としての記載はありませんし。。 Configure Amplify categories - Vue - AWS Amplify Gen 1 Documentation Configuring the client. AWS Amplify Documentation docs.amplify.aws 色々と調べた限り、手動でコンフィグファイルを作成するより、Amplify CLI で経由で各種リソースを構成した際に生成されるコンフィグファイル (src/aws-exports や src/amplifyconfiguration.json) を使用するのが事例としては多いように思えました。そのことも、手動でコンフィグファイルを作成する情報が相対的に少ない原因に繋がっているように思えます。 ただ、今回は別エントリで説明した通りお客さん環境で Amplify を使用できないことが分かっていたこと、Amplify 経由で他サービスを構成した際の細かい設定が難しいことの2点より、Amplify 経由で構成したのは AppSync/DynamoDB のみでした。コンフィグファイル自体も最初から手動で作成する方針で進めていたので、その分時間もかかったような恰好です。 そもそも、コンフィグファイルの書式からして異なっているというのも、構築当初はかなり混乱しました。書式を参考にしようとしても参考にならず、しかしながら Amplify.configure の引数としてはどちらも使用できるというのが・・ What options can I pass to Amplify.configure()? There seem to be two different ways to configure Amplify. Some examples use a key-value properties format:import aws_exp... stackoverflow.com 実際、aws-amplify モジュールは UI 含めて色々と便利で、このモジュールだけを使用したいというケースも全然考えられると思うので、コンフィグ定義一覧程度は公式ドキュメントに載せてくれるとありがたいですね。 ということで、今回の場合の実装例を示してみます。対象は Amplify(GraphQL) 及び Cognito の2種類です。 {   "Auth": {       "Cognito": {           "region": "ap-northeast-1",           "userPoolId": "<Cognito_UserPool_Id>",           "userPoolClientId": "<Cognito_Application_Client_Id>",           "identityPoolId": "<Cognito_IdentityPool_Id>"       }   },   "API": {       "GraphQL": {           "endpoint": "<AppSync_GraphQL_Endpoint_URL>",           "region": "ap-northeast-1",           "defaultAuthMode": "iam"       }   } } なお、他サービスを含めたより詳細な内容については、以下広野さんのエントリも合わせてご参照ください。私も最初にこのエントリを見ていさえすれば、試行錯誤に数時間を費やすところまではいかなかったでしょう・・ aws-amplify と @aws-amplify/ui-react モジュールを v6 にアップデートしてみた aws-amplify と @aws-amplify/ui-react モジュールをバージョン 5 から 6 にアップグレードしたときの対応を紹介します。 blog.usize-tech.com 2023.12.19   Plugin 実装 こちらは、基本的には公式 URL の内容をほぼ踏襲して実装しています。 Use Amplify categories APIs from Nuxt 3 - Next.js - AWS Amplify Gen 1 Documentation Use Amplify categories APIs from Nuxt 3 AWS Amplify Documentation docs.amplify.aws なお、Plugin のファイル名で、client/server のどちらで実行するプラグインかどうかを指定しています。また、Plugin の読込み順序はファイル名(昇順)に従うため、ファイル名の先頭にナンバリングを付与して一番最初に読み込まれるようにしています。 前回のエントリ で記載した通り、他の Plugin 内で aws-amplify/auth (Cognito) や aws-amplify/data (AppSync/GraphQL) の機能を使用しているため、先にこちらの処理を実施しておく必要があるためです。公式 URL の実装例も正にそのようになっていますね。   01.amplifyApis.client.ts client 側で実行する plugin です。先般のエントリで記載した通り、aws-amplify 自体は client 側で実行する前提のモジュールとなっているため、実装内容自体はシンプルです。 今回のアプリケーションで使用するのは Auth/GraphQL の2種類のみであるため、その中から使用する機能やメソッドのみを返すようにしています。また、先に説明した aws-amplify 用の設定ファイルを Amplify.configure の引数で指定しています。 import { Amplify } from 'aws-amplify'; import { fetchAuthSession, fetchUserAttributes, getCurrentUser, signIn, signOut} from "aws-amplify/auth"; import { generateClient } from 'aws-amplify/data'; import { defineNuxtPlugin } from '#app'; import outputs from '../amplify_cognito_setting.json'; const client = generateClient(); export default defineNuxtPlugin({   name: 'AmplifyAPIs',   enforce: 'pre',   setup() {               Amplify.configure(outputs, { ssr: true });       return {           provide: {               Amplify: {                   Auth: {                       fetchAuthSession,                       fetchUserAttributes,                       getCurrentUser,                       signIn,                       signOut                   },                   GraphQL: {                       client                   }               }           }       }   } })   01.amplifyApis.server.ts server 側で実行する plugin です。こちらは率直に言うと、公式 URL の実装例から client の実装をベースに明らかに不要な項目を除外した程度の変更しかしていないため、正直あまり言及できる内容がありません。幸いにも公式 URL の実装例に記載されていた機能/メソッドしか使用しなかったためこのような対応で OK でしたが、他に使用したいものがあった場合はモジュールの実装内容そのものを読み解く必要があったかもしれないです。 認証用の情報を cookie に入れているようで、有効期限が実装例だと30日間となっているため、要件次第でこの点は見直した方が良さそうです。そもそも cookie を使用するかどうかを含めて検討すべきかもしれませんが・・ また、aws-amplify 用の設定ファイルを読み込んでいるのは一緒ですが、Amplify.configure は client 側のメソッドであるため、同設定ファイルから読み込んだ内容をベースに aws-amplify/auth 及び aws-amplify/data ごとに必要な情報をパースしています。 import type { CookieRef } from 'nuxt/app'; import type {   LibraryOptions,   FetchAuthSessionOptions } from '@aws-amplify/core'; import {   createKeyValueStorageFromCookieStorageAdapter,   createUserPoolsTokenProvider,   createAWSCredentialsAndIdentityIdProvider,   runWithAmplifyServerContext } from 'aws-amplify/adapter-core'; import { parseAmplifyConfig } from 'aws-amplify/utils'; import {   fetchAuthSession,   fetchUserAttributes,   getCurrentUser } from 'aws-amplify/auth/server'; import { generateClient } from 'aws-amplify/api/server'; import outputs from '@/amplify_cognito_setting.json'; // parse the content of `amplify_outputs.json` into the shape of ResourceConfig const amplifyConfig = parseAmplifyConfig(outputs); // create the Amplify used token cookies names array const userPoolClientId = amplifyConfig.Auth!.Cognito.userPoolClientId; const lastAuthUserCookieName = `CognitoIdentityServiceProvider.${userPoolClientId}.LastAuthUser`; // create a GraphQL client that can be used in a server context const gqlServerClient = generateClient({ config: amplifyConfig }); const getAmplifyAuthKeys = (lastAuthUser: string) =>   ['idToken', 'accessToken', 'refreshToken', 'clockDrift']       .map(           (key) =>               `CognitoIdentityServiceProvider.${userPoolClientId}.${lastAuthUser}.${key}`       )       .concat(lastAuthUserCookieName); // define the plugin export default defineNuxtPlugin({   name: 'AmplifyAPIs',   enforce: 'pre',   setup() {       // The Nuxt composable `useCookie` is capable of sending cookies to the       // client via the `SetCookie` header. If the `expires` option is left empty,       // it sets a cookie as a session cookie. If you need to persist the cookie       // on the client side after your end user closes your Web app, you need to       // specify an `expires` value.       //       // We use 30 days here as an example (the default Cognito refreshToken       // expiration time).       const expires = new Date();       expires.setDate(expires.getDate() + 30);         // Get the last auth user cookie value       //       // We use `sameSite: 'lax'` in this example, which allows the cookie to be       // sent to your Nuxt server when your end user gets redirected to your Web       // app from a different domain. You should choose an appropriate value for       // your own use cases.       const lastAuthUserCookie = useCookie(lastAuthUserCookieName, {           sameSite: 'lax',           expires,           secure: true       });         // Get all Amplify auth token cookie names       const authKeys = lastAuthUserCookie.value           ? getAmplifyAuthKeys(lastAuthUserCookie.value)           : [];       // Create a key-value map of cookie name => cookie ref       //       // Using the composable `useCookie` here in the plugin setup prevents       // cross-request pollution.       const amplifyCookies = authKeys           .map((name) => ({               name,               cookieRef: useCookie(name, { sameSite: 'lax', expires, secure: true })           }))           .reduce<Record<string, CookieRef<string | null | undefined>>>(               (result, current) => ({                   ...result,                   [current.name]: current.cookieRef               }),               {}           );       // Create a key value storage based on the cookies       //       // This key value storage is responsible for providing Amplify Auth tokens to       // the APIs that you are calling.       //       // If you implement the `set` method, when Amplify needed to refresh the Auth       // tokens on the server side, the new tokens would be sent back to the client       // side via `SetCookie` header in the response. Otherwise the refresh tokens       // would not be propagate to the client side, and Amplify would refresh       // the tokens when needed on the client side.       //       // In addition, if you decide not to implement the `set` method, you don't       // need to pass any `CookieOptions` to the `useCookie` composable.       const keyValueStorage = createKeyValueStorageFromCookieStorageAdapter({           get(name) {               const cookieRef = amplifyCookies[name];               if (cookieRef && cookieRef.value) {                   return { name, value: cookieRef.value };               }               return undefined;           },           getAll() {               return Object.entries(amplifyCookies).map(([name, cookieRef]) => {                   return { name, value: cookieRef.value ?? undefined };               });           },           set(name, value) {               const cookieRef = amplifyCookies[name];               if (cookieRef) {                   cookieRef.value = value;               }           },           delete(name) {               const cookieRef = amplifyCookies[name];               if (cookieRef) {                   cookieRef.value = null;               }           }       });       // Create a token provider       const tokenProvider = createUserPoolsTokenProvider(           amplifyConfig.Auth!,           keyValueStorage       );         // Create a credentials provider       const credentialsProvider = createAWSCredentialsAndIdentityIdProvider(           amplifyConfig.Auth!,           keyValueStorage       );         // Create the libraryOptions object       const libraryOptions: LibraryOptions = {           Auth: {               tokenProvider,               credentialsProvider           }       };         return {           provide: {               // You can add the Amplify APIs that you will use on the server side of               // your Nuxt app here. You must only use the APIs exported from the               // `aws-amplify/<category>/server` subpaths.               //               // You can call the API by via the composable `useNuxtApp()`. For example:               // `useNuxtApp().$Amplify.Auth.fetchAuthSession()`               //               // Recall that Amplify server APIs are required to be called in a isolated               // server context that is created by the `runWithAmplifyServerContext`               // function.               Amplify: {                   Auth: {                       fetchAuthSession: (options: FetchAuthSessionOptions) =>                           runWithAmplifyServerContext(                               amplifyConfig,                               libraryOptions,                               (contextSpec) => fetchAuthSession(contextSpec, options)                           ),                       fetchUserAttributes: () =>                           runWithAmplifyServerContext(                               amplifyConfig,                               libraryOptions,                               (contextSpec) => fetchUserAttributes(contextSpec)                           ),                       getCurrentUser: () =>                           runWithAmplifyServerContext(                               amplifyConfig,                               libraryOptions,                               (contextSpec) => getCurrentUser(contextSpec)                           )                   },                   GraphQL: {                       client: {                           // Follow this typing to ensure the`graphql` API return type can                           // be inferred correctly according to your queries and mutations                           graphql: <                               FALLBACK_TYPES = unknown,                               TYPED_GQL_STRING extends string = string                           >(                               options: GraphQLOptionsV6<FALLBACK_TYPES, TYPED_GQL_STRING>,                               additionalHeaders?: Record<string, string>                           ) =>                               runWithAmplifyServerContext<                                   GraphQLResponseV6<FALLBACK_TYPES, TYPED_GQL_STRING>                               >(amplifyConfig, libraryOptions, (contextSpec) =>                                   gqlServerClient.graphql(                                       contextSpec,                                       options,                                       additionalHeaders                                   )                               )                       }                   }               }           }       };   } });   まとめ コードの分量は多いですが、小ネタに相応しい内容でした。毎回気合いの入ったエントリを書くのがそろそろ難しくなってきたので、こういうちょっとした内容も増やしていければなと思います。(書きながらネタを増やしていけるように努力しているつもりですが・・)ともあれ2桁投稿することが当初の目標だったので、ひとまず達成できてよかったです。 本記事がどなたかの役に立てば幸いです。
こんにちは、SCSKの内ヶ島です。 オンプレミス環境から手軽にAWS Site-to-Site VPN接続の検証環境を構築する方法を紹介します。 この記事では、CloudFormationを使った環境を一括管理し、Amazon Linux 2023のリポジトリに含まれるLibreswanを用いてVPN接続を行います。 はじめに AWS Site-to-Site VPN接続は、オンプレミス環境とAWS環境を安全に接続するための重要な技術です。 しかし、VPN接続の検証には通常、実機のVPN機器が必要となりハードルが高いものでした。 そこで今回の検証では、以下の2点を主な目標として設定しました。 ソフトウェアVPNを用いてVPN接続が正常に機能すること 環境全体をCloudFormationで管理し、簡単に作成・削除できること 実機のVPN機器がなくても、AWSの環境内で完結した形でVPN接続の検証が可能になります。 また、CloudFormationを活用することで、環境の再現性と管理の容易さを実現しています。 環境構成 今回構築する環境は以下の通りです。 オンプレミス側(AWS上に疑似環境として構築)   – VPC (10.0.0.0/22)   – プライベートサブネット (10.0.0.0/24)   – パブリックサブネット (10.0.1.0/24)   – EC2インスタンス x2(VPN装置、クライアント想定) AWS側   – VPC (192.168.0.0/22)   – プライベートサブネット (192.168.0.0/24)   – EC2インスタンス(AWSサーバー想定)   – カスタマーゲートウェイ、仮想プライベートゲートウェイ CloudFormationテンプレート 今回の検証環境構築には、オンプレミス環境用とAWS環境用の2つのCloudFormationテンプレートを使用しています。 CloudFormationテンプレートの特徴 複雑なVPN検証環境を簡単に、そして再現性高く構築することができます。 両環境とも、インターネットに直接接続せずにパッケージ管理やシステム更新が可能な、セキュアな設計となっています。 以下の内容を生成AIを使ってCloudFormationテンプレートを作成しました。 長いテンプレートの記述ミスや整合性をある程度チェックできるので便利です。 共通の特徴 VPC構成 : 両テンプレートともVPCとサブネットを設定 EC2インスタンス : Amazon Linux 2023のEC2インスタンスを作成 セキュリティグループ : 必要最小限のトラフィックのみを許可するセキュリティグループを設定 IAMロールとVPCエンドポイント : Systems Manager Session Managerを使用してEC2インスタンスに接続できるよう、必要なIAMロールとVPCエンドポイント(SSM、EC2メッセージ、SSMメッセージ)を設定 S3 VPCエンドポイント : EC2インスタンスがインターネットを経由せずにS3にアクセスできるよう、S3用のVPCゲートウェイエンドポイントを設定。これにより、dnfやyumを使用したパッケージのインストールが可能となる。 タグ付け : すべてのリソースにタグを付け、管理を容易にしている。タグのプレフィックスはパラメータとして指定可能 オンプレミス環境用テンプレート(Onpre_resource.yaml)の固有の特徴 サブネット構成 : パブリックサブネットとプライベートサブネットの両方を作成 EC2インスタンス(パブリックサブネット) : VPN装置役のEC2インスタンス(Elastic IP付与)。ネットワークの送信元/送信先チェックをオフ EC2インスタンス(プライベートサブネット) : クライアント役のEC2インスタンス ルーティング : プライベートサブネットからのトラフィックをパブリックEC2インスタンス(疑似NATゲートウェイ)経由でルーティング インターネットゲートウェイ : パブリックサブネット用にインターネットゲートウェイを設定 AWS環境用テンプレート(AWS_resource.yaml)の固有の特徴 サブネット構成 : プライベートサブネットのみを作成します。 VPNリソース : カスタマーゲートウェイ、仮想プライベートゲートウェイ、VPN接続、VPN接続ルートを作成 パラメータ : カスタマーゲートウェイのIPアドレスをパラメータとして受け取る EC2インスタンス : プライベートサブネット内に1つのEC2インスタンスを作成(VPN経由でアクセスされるサーバー役) CloudFormationテンプレート オンプレミス環境用テンプレート(Onpre_resource.yaml) AWSTemplateFormatVersion: '2010-09-09' Description: 'VPC with Public and Private Subnets, EC2 Instances, SSM access, and S3 Endpoint' Parameters: TagPrefix:   Type: String   Default: '00000'   Description: 'Prefix for resource tags' AmazonLinux2023AMI:   Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>   Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64 Resources: VPC:   Type: AWS::EC2::VPC   Properties:     CidrBlock: 10.0.0.0/22     EnableDnsHostnames: true     EnableDnsSupport: true     Tags:       - Key: Name         Value: !Sub '${TagPrefix}-VPC'   InternetGateway:   Type: AWS::EC2::InternetGateway   Properties:     Tags:       - Key: Name         Value: !Sub '${TagPrefix}-IGW'   InternetGatewayAttachment:   Type: AWS::EC2::VPCGatewayAttachment   Properties:     InternetGatewayId: !Ref InternetGateway       VpcId: !Ref VPC PublicSubnet:   Type: AWS::EC2::Subnet   Properties:     VpcId: !Ref VPC     AvailabilityZone: !Select [0, !GetAZs '']     CidrBlock: 10.0.1.0/24     MapPublicIpOnLaunch: true     Tags:       - Key: Name           Value: !Sub '${TagPrefix}-Public-Subnet' PrivateSubnet:   Type: AWS::EC2::Subnet   Properties:     VpcId: !Ref VPC     AvailabilityZone: !Select [1, !GetAZs '']     CidrBlock: 10.0.0.0/24     MapPublicIpOnLaunch: false     Tags:       - Key: Name           Value: !Sub '${TagPrefix}-Private-Subnet' PublicRouteTable:   Type: AWS::EC2::RouteTable   Properties:     VpcId: !Ref VPC     Tags:       - Key: Name           Value: !Sub '${TagPrefix}-Public-RT' PrivateRouteTable:   Type: AWS::EC2::RouteTable   Properties:     VpcId: !Ref VPC     Tags:       - Key: Name           Value: !Sub '${TagPrefix}-Private-RT' PublicRoute:   Type: AWS::EC2::Route   DependsOn: InternetGatewayAttachment   Properties:     RouteTableId: !Ref PublicRouteTable     DestinationCidrBlock: 0.0.0.0/0       GatewayId: !Ref InternetGateway PrivateRoute:   Type: AWS::EC2::Route   Properties:     RouteTableId: !Ref PrivateRouteTable     DestinationCidrBlock: 0.0.0.0/0       InstanceId: !Ref PublicEC2Instance PublicSubnetRouteTableAssociation:   Type: AWS::EC2::SubnetRouteTableAssociation   Properties:     SubnetId: !Ref PublicSubnet       RouteTableId: !Ref PublicRouteTable PrivateSubnetRouteTableAssociation:   Type: AWS::EC2::SubnetRouteTableAssociation   Properties:     SubnetId: !Ref PrivateSubnet       RouteTableId: !Ref PrivateRouteTable PublicSecurityGroup:   Type: AWS::EC2::SecurityGroup   Properties:     GroupName: !Sub '${TagPrefix}-Public-SG'     GroupDescription: 'Security group for public EC2 instance'     VpcId: !Ref VPC     SecurityGroupIngress:       - IpProtocol: -1         FromPort: -1         ToPort: -1         CidrIp: 10.0.0.0/22     SecurityGroupEgress:       - IpProtocol: -1         FromPort: -1         ToPort: -1         CidrIp: 0.0.0.0/0     Tags:       - Key: Name           Value: !Sub '${TagPrefix}-Public-SG' PrivateSecurityGroup:   Type: AWS::EC2::SecurityGroup   Properties:     GroupName: !Sub '${TagPrefix}-Private-SG'     GroupDescription: 'Security group for private EC2 instance'     VpcId: !Ref VPC     SecurityGroupIngress:       - IpProtocol: -1         FromPort: -1         ToPort: -1         SourceSecurityGroupId: !Ref PublicSecurityGroup     SecurityGroupEgress:       - IpProtocol: -1         FromPort: -1         ToPort: -1         CidrIp: 0.0.0.0/0     Tags:       - Key: Name           Value: !Sub '${TagPrefix}-Private-SG' EndpointSecurityGroup:   Type: AWS::EC2::SecurityGroup   Properties:     GroupName: !Sub '${TagPrefix}-Endpoint-SG'     GroupDescription: 'Security group for VPC Endpoints'     VpcId: !Ref VPC     SecurityGroupIngress:       - IpProtocol: tcp         FromPort: 443         ToPort: 443         SourceSecurityGroupId: !Ref PrivateSecurityGroup       - IpProtocol: tcp         FromPort: 443         ToPort: 443         SourceSecurityGroupId: !Ref PublicSecurityGroup     Tags:       - Key: Name           Value: !Sub '${TagPrefix}-Endpoint-SG' PublicEC2Instance:   Type: AWS::EC2::Instance   Properties:     InstanceType: t3.micro     ImageId: !Ref AmazonLinux2023AMI     SubnetId: !Ref PublicSubnet     SecurityGroupIds:       - !Ref PublicSecurityGroup     IamInstanceProfile: !Ref EC2InstanceProfile     SourceDestCheck: false     Tags:       - Key: Name           Value: !Sub '${TagPrefix}-Onpre-Public-EC2' PrivateEC2Instance:   Type: AWS::EC2::Instance   Properties:     InstanceType: t3.micro     ImageId: !Ref AmazonLinux2023AMI     SubnetId: !Ref PrivateSubnet     SecurityGroupIds:       - !Ref PrivateSecurityGroup     IamInstanceProfile: !Ref EC2InstanceProfile     Tags:       - Key: Name           Value: !Sub '${TagPrefix}-Onpre-Private-EC2' PublicEIP:   Type: AWS::EC2::EIP   Properties:     Domain: vpc     InstanceId: !Ref PublicEC2Instance     Tags:       - Key: Name           Value: !Sub '${TagPrefix}-Public-EIP' EC2InstanceProfile:   Type: AWS::IAM::InstanceProfile   Properties:     Path: "/"     Roles:         - !Ref EC2SSMRole S3Endpoint:   Type: AWS::EC2::VPCEndpoint   Properties:     VpcId: !Ref VPC     ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3'     VpcEndpointType: Gateway     RouteTableIds:         - !Ref PrivateRouteTable EC2SSMRole:   Type: AWS::IAM::Role   Properties:     AssumeRolePolicyDocument:       Version: "2012-10-17"       Statement:         - Effect: Allow           Principal:             Service:               - ec2.amazonaws.com           Action:             - sts:AssumeRole     ManagedPolicyArns:       - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore       - arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess     Tags:       - Key: Name           Value: !Sub '${TagPrefix}-EC2-SSM-Role' SSMEndpoint:   Type: AWS::EC2::VPCEndpoint   Properties:     ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ssm'     VpcId: !Ref VPC     VpcEndpointType: Interface     PrivateDnsEnabled: true     SubnetIds:       - !Ref PrivateSubnet       - !Ref PublicSubnet     SecurityGroupIds:         - !Ref EndpointSecurityGroup SSMMessagesEndpoint:   Type: AWS::EC2::VPCEndpoint   Properties:     ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ssmmessages'     VpcId: !Ref VPC     VpcEndpointType: Interface     PrivateDnsEnabled: true     SubnetIds:       - !Ref PrivateSubnet       - !Ref PublicSubnet     SecurityGroupIds:         - !Ref EndpointSecurityGroup Outputs: PublicEC2InstanceId:   Description: 'Public EC2 Instance ID'   Value: !Ref PublicEC2Instance PrivateEC2InstanceId:   Description: 'Private EC2 Instance ID'   Value: !Ref PrivateEC2Instance PublicEIP:   Description: 'Elastic IP for Public EC2 Instance'   Value: !Ref PublicEIP AWS環境用テンプレート(AWS_resource.yaml) AWSTemplateFormatVersion: '2010-09-09' Description: 'VPC with Private Subnet, EC2 Instance, Site-to-Site VPN, and S3 Endpoint' Parameters: TagPrefix:   Type: String   Default: '00000'   Description: 'Prefix for resource tags' CustomerGatewayIp:   Type: String   Description: 'Public IP address of your Customer Gateway' AmazonLinux2023AMI:   Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>   Default: '/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64'   Description: 'Amazon Linux 2023 AMI ID' Resources: VPC:   Type: AWS::EC2::VPC   Properties:     CidrBlock: 192.168.0.0/22     EnableDnsHostnames: true       EnableDnsSupport: true     Tags:       - Key: Name         Value: !Sub '${TagPrefix}-VPC'   PrivateSubnet:   Type: AWS::EC2::Subnet   Properties:     VpcId: !Ref VPC     AvailabilityZone: !Select [0, !GetAZs '']     CidrBlock: 192.168.0.0/24     MapPublicIpOnLaunch: false     Tags:       - Key: Name         Value: !Sub '${TagPrefix}-Private-Subnet'   PrivateRouteTable:   Type: AWS::EC2::RouteTable   Properties:     VpcId: !Ref VPC     Tags:       - Key: Name         Value: !Sub '${TagPrefix}-Private-RT'   PrivateSubnetRouteTableAssociation:   Type: AWS::EC2::SubnetRouteTableAssociation   Properties:     SubnetId: !Ref PrivateSubnet     RouteTableId: !Ref PrivateRouteTable   VPNSecurityGroup:   Type: AWS::EC2::SecurityGroup   Properties:     GroupName: !Sub '${TagPrefix}-VPN-SG'     GroupDescription: 'Security group for VPN connection and SSM'     VpcId: !Ref VPC     SecurityGroupIngress:       - IpProtocol: -1         FromPort: -1         ToPort: -1         CidrIp: 10.0.0.0/22       - IpProtocol: tcp         FromPort: 443         ToPort: 443         CidrIp: 192.168.0.0/22     Tags:       - Key: Name         Value: !Sub '${TagPrefix}-VPN-SG'   EC2Instance:   Type: AWS::EC2::Instance   Properties:     InstanceType: t3.micro     ImageId: !Ref AmazonLinux2023AMI     SubnetId: !Ref PrivateSubnet     SecurityGroupIds:       - !Ref VPNSecurityGroup     IamInstanceProfile: !Ref EC2InstanceProfile     Tags:       - Key: Name         Value: !Sub '${TagPrefix}-AWS-Private-EC2'   EC2InstanceProfile:   Type: AWS::IAM::InstanceProfile   Properties:     Path: "/"     Roles:       - !Ref EC2SSMRole   S3Endpoint:   Type: AWS::EC2::VPCEndpoint   Properties:     VpcId: !Ref VPC     ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3'     VpcEndpointType: Gateway     RouteTableIds:       - !Ref PrivateRouteTable   EC2SSMRole:   Type: AWS::IAM::Role   Properties:     AssumeRolePolicyDocument:       Version: "2012-10-17"       Statement:         - Effect: Allow           Principal:             Service:               - ec2.amazonaws.com           Action:             - sts:AssumeRole     ManagedPolicyArns:       - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore       - arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess     Tags:       - Key: Name         Value: !Sub '${TagPrefix}-EC2-SSM-Role'   CustomerGateway:   Type: AWS::EC2::CustomerGateway   Properties:     Type: ipsec.1     BgpAsn: 65000     IpAddress: !Ref CustomerGatewayIp     Tags:       - Key: Name         Value: !Sub '${TagPrefix}-CustomerGateway'   VirtualPrivateGateway:   Type: AWS::EC2::VPNGateway   Properties:     Type: ipsec.1     Tags:       - Key: Name         Value: !Sub '${TagPrefix}-VPNGateway'   VPNGatewayAttachment:   Type: AWS::EC2::VPCGatewayAttachment   Properties:     VpcId: !Ref VPC     VpnGatewayId: !Ref VirtualPrivateGateway   VPNConnection:   Type: AWS::EC2::VPNConnection   DependsOn:     - VirtualPrivateGateway     - VPNGatewayAttachment   Properties:     Type: ipsec.1     CustomerGatewayId: !Ref CustomerGateway     VpnGatewayId: !Ref VirtualPrivateGateway     StaticRoutesOnly: true     Tags:       - Key: Name         Value: !Sub '${TagPrefix}-VPNConnection'   VPNConnectionRoute:   Type: AWS::EC2::VPNConnectionRoute   DependsOn: VPNConnection   Properties:     DestinationCidrBlock: 10.0.0.0/22     VpnConnectionId: !Ref VPNConnection   VPNRoute:   Type: AWS::EC2::Route   DependsOn: VPNGatewayAttachment   Properties:     RouteTableId: !Ref PrivateRouteTable     DestinationCidrBlock: 10.0.0.0/22     GatewayId: !Ref VirtualPrivateGateway   SSMEndpoint:   Type: AWS::EC2::VPCEndpoint   Properties:     VpcId: !Ref VPC     ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ssm'     VpcEndpointType: Interface     PrivateDnsEnabled: true     SubnetIds:       - !Ref PrivateSubnet     SecurityGroupIds:       - !Ref VPNSecurityGroup   EC2MessagesEndpoint:   Type: AWS::EC2::VPCEndpoint   Properties:     VpcId: !Ref VPC     ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ec2messages'     VpcEndpointType: Interface     PrivateDnsEnabled: true     SubnetIds:       - !Ref PrivateSubnet     SecurityGroupIds:       - !Ref VPNSecurityGroup   SSMMessagesEndpoint:   Type: AWS::EC2::VPCEndpoint   Properties:     VpcId: !Ref VPC     ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ssmmessages'     VpcEndpointType: Interface     PrivateDnsEnabled: true     SubnetIds:       - !Ref PrivateSubnet     SecurityGroupIds:       - !Ref VPNSecurityGroup Outputs: EC2InstanceId:   Description: 'EC2 Instance ID'   Value: !Ref EC2Instance CustomerGatewayId:   Description: 'Customer Gateway ID'   Value: !Ref CustomerGateway VirtualPrivateGatewayId:   Description: 'Virtual Private Gateway ID'   Value: !Ref VirtualPrivateGateway VPNConnectionId:   Description: 'VPN Connection ID'   Value: !Ref VPNConnection 環境構築手順 なるべく少ない手数で再現性のある構築を進めるため、CloudShellでAWS CLIを用いて作業します。 AWSマネジメントコンソールの上部または左下の「>_」マークをクリックします。 立ち上がってきたCloudShell画面で「Open <リージョン名> environment」をクリックします。 Shellを打ち込める画面が出てきます。 # タグのプレフィックスを設定(任意の文字列を指定してください) TAGPREFIX=00000 # オンプレ側構築 aws cloudformation deploy \     --stack-name "VPNtest-Onpre-${TAGPREFIX}" \     --template-file Onpre_resource.yaml \     --capabilities CAPABILITY_IAM \     --parameter-overrides TagPrefix=${TAGPREFIX} # オンプレ側のVPN機器となるEC2インスタンスのGlobalIPを取得 GLOBALIP=`aws ec2 describe-addresses --query 'Addresses[].PublicIp' --filter "Name=tag:Name,Values=${TAGPREFIX}-Public-EIP" --output text` && echo ${GLOBALIP} # AWS側構築 aws cloudformation deploy \     --stack-name "VPNtest-AWS-${TAGPREFIX}" \     --template-file AWS_resource.yaml \     --capabilities CAPABILITY_IAM \   --parameter-overrides TagPrefix=${TAGPREFIX} CustomerGatewayIp=${GLOBALIP} VPN設定 AWS Site-to-Site VPNではオンプレ側VPN機器の設定サンプルをダウンロードできます。 オンプレ側ではソフトウェアVPNのLibreswanを使用しますが、該当するものがないので類似するOpenswanの設定サンプルをダウンロードします。 VPN設定ダウンロード [VPC] – [Site-to-Site VPN 接続] [設定をダウンロードする] [ベンダー] Openswan [プラットフォーム] Openswan [ソフトウェア] Openswan 2.6.38+ [IKEバージョン] ikev1 を指定し、[ダウンロード] ここでダウンロードした設定ファイルの一部を用いて、Libreswanの設定をしていきます。 Libreswan設定 LibreswanからAWS Site-to-Site VPNへの接続に利用するトンネルは1本のみとします。(2本用いるHA構成も可能だが「気軽な」検証にならないため) AWS Systems Manager Session Managerを用いてオンプレ側Public EC2インスタンスにログインします。 [EC2] – [インスタンス] より、ログインしたいインスタンスにチェックを入れ、[接続] をクリックします。 [セッションマネージャー] タブを選択し、[接続] をクリックします。 # Libreswanインストール sudo dnf install -y libreswan # カーネルパラメータ修正 echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.d/custom-ip-forwarding.conf sudo sysctl -p /etc/sysctl.d/custom-ip-forwarding.conf # Libreswan設定 sudo vi /etc/ipsec.conf config setup ブロックに下記設定のみを追記します。         protostack=netkey # ダウンロードしたVPN設定から接続部分を抜き出して貼り付け、内容を書き換える # Tunnel1の部分のみ。 sudo vi /etc/ipsec.d/aws.conf conn Tunnel1 authby=secret auto=start left=%defaultroute leftid= <オンプレ側のGlobalIP>   # 記載のものをそのまま入力 right= <AWS側のGlobalIP>   # 記載のものをそのまま入力 type=tunnel ikelifetime=8h keylife=1h phase2alg=aes128-sha1; modp2048  # 末尾のmodp1024をmodp2048に変更 ike=aes128-sha1; modp2048        # 末尾のmodp1024をmodp2048に変更 auth=esp                      # この行は削除 keyingtries=%forever keyexchange=ike leftsubnet=10.0.0.0/22          # leftがオンプレ側(今設定しているほう) rightsubnet=192.168.0.0/22      # rightがAWS側 dpddelay=10 dpdtimeout=30                   # この行は削除 retransmit-timeout=30s          # この行を追加 dpdaction=restart_by_peer # シークレット情報を張り付ける # ※Tunnel1もののみをそのまま貼り付け、Tunnel2のキーは貼り付けない sudo vi /etc/ipsec.d/aws.secrets <オンプレ側のGlobalIP> <AWS側のGlobalIP> : PSK " <キー情報> " sudo systemctl start ipsec sudo systemctl status ipsec exit VPNトンネル接続確認 [VPC] – [Site-to-Site VPN] 作成したVPN接続を選択 [トンネルの詳細] タブを選択 1つのトンネルが接続されていることを確認します。(リロードしながら少し待つ必要があります) もう一つはダウンのままで構いません。 接続確認 IPアドレスを確認 TAGPREFIX=00000 aws ec2 describe-instances \     --filters "Name=instance-state-name,Values=running" "Name=tag:Name,Values=*${TAGPREFIX}*" \     --query "Reservations[*].Instances[*].[PrivateIpAddress, Tags[?Key=='Name'].Value | [0]]" \   --output text 以下のようにIPアドレスが出力されます。このIPアドレスを用いて接続確認をしていきます。 10.0.0.148      00000-Onpre-Private-EC2 192.168.0.34   00000-AWS-Private-EC2 10.0.1.145      00000-Onpre-Public-EC2 通信確認 pingによる通信確認 AWS Systems Manager Session Managerを用いて オンプレ側プライベートEC2 へログインします。 # AWS側プライベートEC2のIPに向けて通信確認 ping 192.168.0.34 →オンプレ側からAWS側へ通信できることを確認します。 同じく、 AWS側プライベートEC2 へログインします。 ping 10.0.0.148 →AWS側からオンプレ側へ通信できることを確認します。 HTTPによる通信確認 AWS側プライベートEC2 で下記を実行します。 cd ~ touch iam_aws_private python3 -m http.server 8000 今度は、 オンプレ側プライベートEC2 で下記を実行します。 curl 192.168.0.34:8000 →ディレクトリの中身が見えることを確認します(VPN接続先のiam_aws_privateファイルが見える) AWS側プライベートEC2で、オンプレ側からアクセスがあったログを確認できます。 オンプレ側の通信確認 AWS側の通信確認 トラブルシューティング VPN接続で問題が発生した場合は、以下の点を確認してください セキュリティグループの設定 ルートテーブルの設定 Libreswanの設定ファイル VPNログ(sudo journalctl -u ipsec) クリーンアップ 検証が終わったら、以下のコマンドで環境を削除します # CloudFormationスタックを削除 aws cloudformation delete-stack --stack-name "VPNtest-Onpre-${TAGPREFIX}" aws cloudformation delete-stack --stack-name "VPNtest-AWS-${TAGPREFIX}" # スタック削除を待つ aws cloudformation wait stack-delete-complete --stack-name "VPNtest-Onpre-${TAGPREFIX}" & aws cloudformation wait stack-delete-complete --stack-name "VPNtest-AWS-${TAGPREFIX}" & wait # 2つのスタックが削除され、プロンプトが戻れば終了 CloudShellの終了は、CloudShell画面の [アクション] – [削除] を選択し、表示された確認画面で「delete」と入力し、[削除] ボタンを押します。 参考資料 ソフトウェア VPN から AWS Site-to-Site VPN https://docs.aws.amazon.com/ja_jp/whitepapers/latest/aws-vpc-connectivity-options/software-vpn-to-aws-site-to-site-vpn.html OS設定でNATインスタンスのチュートリアルを参考にしました(特にnet.ipv4.ip_forward=1の設定) https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/work-with-nat-instances.html SSMへの接続用VPCエンドポイントを作成の際、ec2messages:* エンドポイントは作成の必要がなくなりました。 https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-setting-up-messageAPIs.html SSM Agent のバージョン 3.3.40.0 以降、Systems Manager は、使用可能な場合には ec2messages:* エンドポイント (Amazon Message Delivery Service) の代わりに ssmmessages:* エンドポイント (Amazon Message Gateway Service) を使用するようになりました。   まとめ 今回の記事では、AWSでのSite-to-Site VPN接続の検証環境構築方法を紹介しました。CloudFormationを使うことで、複雑な環境も簡単に構築・管理できることがお分かりいただけたかと思います。 実際の本番環境では、セキュリティやパフォーマンスなどさらに考慮すべき点がありますが、この記事がVPN検証の参考になれば幸いです。
こんにちは、佐藤と申します! 今回が記念すべき初執筆! ということでつたない点もあるとは思いますが、少しでも面白いと思っていただける記事を書けるよう頑張ります! さて、今回は昨年末のAWS re:Inventにて、2025年からすべてのユーザーがクレジットカードなしで毎日無料で使えるようになるという素晴らしい発表があった PartyRock が主役。 PartyRockに理想のデートプランを考えさせてみた結果が……というお話です。ぜひ最後までお読みいただければ幸いです。   きっかけはこんな記事から… 56.4%――――。 これ何の数字かわかりますか? マイナビウーマンさんが『マイナビウーマン』にて2014年11月にとったWebアンケートによると、 56.4%の人がデートプランを前もって決めたい派 なんだそうです(参考 https://woman.mynavi.jp/article/141206-7/ )。皆さんはこの数字をどのように捉えるでしょうか? 確かにデートプランが事前にわかることでその日1日をどう過ごすのか、どんな服装でどこに集合すればいいのかを逆算することができますよね。 でも正直、 「デートプランを考えるの、めんどくさいんだよな…」 って方も少なくないのではないでしょうか? それならば!お手伝いしてもらいましょう! 誰に…? もちろんPartyRockにです!   ちなみにPartyRockってなに…? 初めて聞いた方のために、PartyRockについて簡単に補足を入れておきます。 PartyRockとは、 AWSが提供する生成AIアプリケーションをプロンプトのみ、ノーコードで作成することのできるサービス です。 こちらの公式ドキュメントから詳しい使い方等は確認いただけます。→  https://aws.amazon.com/jp/blogs/news/create-generative-ai-app-with-partyrock-amazon-bedrock/ PartyRockは、同じくAWSが提供する生成AIサービスであるAmazon Bedrockと統合されているため、 さまざまなAIモデルを使用することができ 、基本操作は テキスト入力 とUIをいじるための ドラッグアンドドロップ が主となんとも使いやすい仕様なのが特徴です。 2024年までは無料トライアル期間を設けており、その期間で限られたトークン分しか使用することができませんでしたが、上述の通り、 昨年末のAWS re:Inventでトライアル期間を気にせずに使用できることが発表されました。 →  https://aws.amazon.com/jp/about-aws/whats-new/2024/12/partyrock-app-discovery-upcoming-free-daily-use/ まさに触ってみなきゃ損!なサービスと言っても過言ではないのがPartyRockなんです。 PartyRockを最強のデートプランナーにしてみる PartyRockにログインしてみよう そうと決まれば、早速PartyRockにログインしてみましょう。 PartyRockへはこちらのURLからアクセスすることができます→  https://partyrock.aws/ 左上の 「Log in」 ボタンをクリックするとこのようなログイン画面が表示されます。 PartyRockへのログインは、 Googleアカウント 、 Appleアカウント からでも可能です! AWSアカウントをまだお持ちでない方でも試せるのはありがたいですよね。 早速ログインができたら、 「Generate app」 ボタンからアプリを作っていきましょう。   プロンプトからアプリを作成しよう するとアプリ構築のベースとなるプロンプトを入力する画面が表示されるので、大まかな目的や、ほしい機能を記載していきましょう。 今回はこんなプロンプトを作成してみました。 あなたは世界一のデートプランナーです。絶対に失敗できないデートがあります。相手の心をつかみ、二人の距離を一気に縮めるような絶対に成功するデートプランを作成してください。当日の詳細な流れ、おすすめスポット、会話のヒントを具体的かつ分かりやすく記述してください。 場所:@場所 予算:@予算 相手の趣味:@相手の趣味 キーワード:@キーワード(例:ロマンチック、アウトドア、サプライズ、音楽) 時間帯:@時間帯 ちなみに後半に一部入っている 「@」 があると思いますが、これは場所~時間帯までの要素が 変数(プレイスホルダー) であることをAIに明示するためのものです。 プロンプトを受け取るAI側は、これらがユーザーが定義した値が入るものとして結果を出力します。 これによりユーザーは変数に好きな条件を入れてデートプランを作成することができるようになるのです。 さて、30秒ほど待つと具体的なデートプランを考えるためのユーザー入力画面が出力されます。 先ほど指示した場所から時間帯まで5つの入力項目があるので、今回はこんな条件を入れてみました。 デートの場所:東京。できるだけ歩いて移動できる距離がいいかな。 予算:30000円くらい。 相手の趣味:音楽。音楽に関するデートができたら理想的。 キーワード:ロマンチック、サプライズ 時間帯:終日。お昼ごろから夜までで考えてみて。   予算30,000円はさすがにやりすぎましたかね…笑 私は普段からかなり音楽を聴くので、今回は音楽に関連するデートということでPartyRockにお願いしてみました。 果たしてその結果は…… 理想のデートプラン、その結果は…? PartyRock、只者ではないな……? まずは今回のデートの概要から。 音楽をテーマにした、ロマンチックで思い出に残る東京デートプランです。 昼から夜にかけて、音楽関連スポットを巡り、ライブ演奏を楽しみ、最後はサプライズで締めくくります。 お、なかなか悪くないですね。 これはかなり良い出力を期待してしまいます。 次が最も大切。1日のスケジュールです。 12:00 – 渋谷駅集合 12:15 – タワーレコード渋谷店でショッピング 13:30 – 代官山のカフェでランチ 15:00 – 恵比寿ガーデンプレイスでストリートミュージシャン鑑賞 16:30 – 目黒川沿いを散歩 18:00 – 中目黒のジャズバーでディナーとライブ 21:00 – 東京タワーで夜景鑑賞 22:30 – デート終了 思いのほかよさそうな気がしますね…笑 てっきり「いや、場所東京じゃないんかい!!」ってツッコミが必要かと思っていたのでこれは意外でした。 時間帯も昼から夜にかけてと完璧な出来です。 よくみると15時から恵比寿ガーデンプレイスで1時間近くストリートミュージシャンを眺める謎の時間発生してたりしますが…… しかもPartyRock、具体的な場所まで提案してくれているんです。 例えば13:30からの代官山のカフェでのランチ。 ここでは実際に渋谷に存在する「 茶亭 羽當」さんを紹介していました。 茶亭 羽當さんについてはこちらから→   https://tabelog.com/tokyo/A1303/A130301/13001169/ ちなみにPartyRockいわく、 おしゃれな雰囲気で 軽いランチを楽しめる BGMも洗練されており、 音楽好きにぴったり とのことで、音楽にもきちんと絡めてくれています。すごい…… しかし思いがけない落とし穴が… PartyRockに感心するのも束の間、1つ 大きな落とし穴 がありました。 それが、 移動距離 です。 今回のデートでは、「できるだけ歩いて行ける距離で」という条件を付けました。 実際にPartyRockが提案してくれたルートを調べてみると… 総移動距離、驚異の 14.2km 。 約3時間半 を徒歩移動に費やす計算になります。ちょっと歩けないかも…… 特に遠かったのが18時半から行く予定のジャズバー。 ということでPartyRockに場所を変えてほしいと要望を伝えてみると… なんと新たに3か所、候補となるジャズバーを紹介してくれました! ですが、なぜかすべて中目黒。なぜか渋谷方面には寄ってくれませんでした…。 PartyRockではこんな設定も可能なんです ちなみにPartyRockが最初に出力してくれたユーザー画面ですが、これも プロンプトを変更して出力を調整することも可能 です。 さらには 使用するAIモデルまで選択可能! デフォルトはClaudeになっていますが、Amazon Novaに変更して出力してみるとこんな感じになりました。 12:00 – 渋谷駅集合 12:15 – タワーレコード渋谷店でショッピング 13:30 – 代官山のカフェでランチ 15:00 – 恵比寿ガーデンプレイスで ウィンドウショッピングと散策 17:00 – 代官山蔦屋書店で音楽関連の本を探索 18:30 – 中目黒のイタリアンレストランでディナー 20:30 – 中目黒川沿いの散歩とサプライズライブ 何かあまり変わっていないような…笑 恵比寿ガーデンプレイスでショッピングを追加してくれたことは救いでしょうか…? また、 作ったアプリケーションはURLで共有することも可能 です。 URLで簡単に共有ができるお手軽さも素晴らしいです! 結論、PartyRockは… 実際にPartyRockを使ってみて、 生成AIサービス、特にアプリケーションを作成する類の中ではかなり使いやすい なというのが正直な感想です。 日本語対応 していて UIもかなり使いやすい 、 URLで簡単に共有 できる点も利用までの心理的ハードルが低くなるポイントだったと感じています。 そして何より一番の気づきは、 PartyRockは中目黒がおしゃれの頂点だと思っている説 …笑 何度か試しましたが渋谷・目黒エリアしか出してくれず、思いがけずPartyRockの好みまでわかってしまいました。 最後まで読んでいただきありがとうございました。 少しでも興味を持った方はぜひPartyRockでアイデアを形にする楽しさを味わってみてはいかがでしょうか?
こんにちは。SCSK株式会社の上田です。 Zabbixに関する、 深刻な脆弱性 が発表されました。 この脆弱性は、 Zabbixのバージョン5.0.45、6.0.33、6.4.18、7.0.3までのバージョン に影響します。 Zabbixをご利用の方は一度ご覧いただき、対象の場合はアップデート等のご検討お願い致します。 脆弱性情報 概要 HTTPリクエストオブジェクトのサーバーレスポンスヘッダー取得機能に脆弱性があり、受信したレスポンスのヘッダー内にある一部文字列の安全性チェックに不足があります。ヘッダー内に悪意のある文字列が入力されることにより、 Zabbixサーバ上でメモリの内容を読み取ったり、任意のコードを実行する恐れ があります。 対象コンポーネント Zabbixサーバ 対象バージョン 以下の Zabbix バージョンが影響を受けます。 Zabbix 5.0.0 – 5.0.45 Zabbix 6.0.0 – 6.0.33 Zabbix 6.4.0 – 6.4.18 Zabbix 7.0.0 – 7.0.3 影響 攻撃者が細工したHTTPヘッダーを送信することで、サーバー上の機密情報にアクセスしたり、任意のコードを実行したりする可能性があります。 回避方法 この脆弱性を回避するためには、Zabbixの最新バージョンにアップデートすることが推奨されます。 Zabbix 5.0.46以降 Zabbix 6.0.34以降 Zabbix 6.4.19以降 Zabbix 7.0.4移行 最後に 弊社では本件に関してのお問い合わせもお受けしております。 ご相談事項がございましたら、以下ページよりお問い合わせいただければと思います。 お問い合わせ 製品・サービスについて 入力 | SCSK株式会社 SCSK株式会社 製品・サービスについてご意見・ご質問をお受けしております。 www.scsk.jp また、弊社では Zabbixのバージョンアップの支援 も行っております。 ご興味のある方は、是非弊社までお問合せください。 最後まで読んでいただき、ありがとうございました。 弊社ではZabbix関連サービスを展開しています。以下ページもご参照ください。 ★Zabbixの基礎をまとめたeBookを公開しております!★ FAQ・お問い合わせ|SCSK Plus サポート for Zabbix 導入をご検討される際、よくあるご質問と回答についてまとめております。 www.scsk.jp ★SCSK Plus サポート for Zabbix★ SCSK Plus サポート for Zabbix 世界で最も人気のあるオープンソース統合監視ツール「Zabbix」の導入構築から運用保守までSCSKが強力にサポートします www.scsk.jp ★YouTubeに、SCSK Zabbixチャンネルを開設しました!★ SCSK Zabbixチャンネル 本チャンネルでは、SCSK株式会社でのZabbixに関するトレンド/事例紹介などを動画にまとめて取り上げております。最新のトピックについては、以下の弊社HPもしくはツイッターアカウントをぜひ参照ください。ツイッターアカウント: www.youtube.com ★X(旧Twitter)に、SCSK Zabbixアカウントを開設しました!★ x.com x.com
はじめに いきなりですが、パフォーマンスチューニングの極意からお話しましょう。 パフォーマンスチューニングとは、「一定の制約の中で、希望の結果を選び取ること」と考えると、我々人類が日々行っている生存競争と何ら変わりがありません。日々生存競争している、すなわち、常在戦場。つまり戦場の極意=パフォーマンスチューニングの極意でもあるということにほかなりません。 ここで、歴史上の偉人に登場してもらって、戦場での極意を語ってもらいましょう。 孫子曰く、 「敵を知り己を知らば百戦あやうからず」 \孫子言いたいだけだろ/ ハイ、その通りです。 敵?己? 今回は、Webサイトのパフォーマンス・チューニングを例としてチューニングを行います。 敵と己にわけて考えます。別に悪意があって敵とするわけではなくて、自分の努力、パフォーマンスチューニングではどうしようもないものを敵と捉えます。自分の手の届く範囲の外にあるもの、と、捉えてもいいですね。 逆に自分でどうにかできるものや、できそうなものを己とします。 敵 Webサーバーに殺到するお客様、あるいはWebサーバーを乗っ取ろうとする攻撃者 己 Webサーバーの特性、Webサイトのアーキテクチャー構成、ネットワーク構成、Webサーバーやシステムの得意技、苦手とするところ、業務要件、制約事項、コンテンツの特性、etc… こうやって見ると己はすごく多いですね。 パフォーマンス・チューニングの流れ パフォーマンス・チューニングの流れとしては、下の図のようになります。 左上のスタートから始まって、ぐるっと回るような流れになっています。   データ収集 データ分析 結果判定 ボトルネック特定 ボトルネック改善 測定試験実行 順に見ていきましょう。 1. データ収集 「Webサイトの表示が重くなってきて、最終的に表示されなくなった」「イベントのときにいきなり落ちた」など、訴え事象やお客様からみた状態「だけ」では、Webサイトの中で何が起こっているのか全くわかりません。まずは状況を客観的に判断するためのデータを収集します。 Webサイトであれば、 Webサーバのアクセスログ エラーログ(Webサーバーが 4xx,5xx を返却したログ、あるいはアプリケーションが異常時に出力したログ) EC2 や RDS を利用している場合は、CPU利用率や、メモリ利用率 Akamai, CloudFrontな どのコンテンツデリバリーネットワーク(CDN)サービスを利用しているのではあれば、その統計データ などのデータがあると思います。そういったデータの中から、 異常発生時の状態のログ 普段の正常な状態のログ できれば異常発生時と同じようなイベントの際のデータと、イベントのない平常時の同じ曜日時間帯など比較できる状況別にあると望ましい と両方を比較できるようにデータを取得します。 そういったデータがそもそも取得されていないのであれば、まずは取得するところからになってしまいますが、何が起こっているのか全くわからない状況ではどうすればよいのか判断できないので、早速取得を開始しましょう。最低限上記のログと、アプリケーションのログを出力して取得する必要があります。 ある時点でWebサイトがお客様からどのように見えていたかを常時確認するのは困難なため、自動化がおすすめです。 CloudWatch Synthetics Canary などを使って定期的に観測しましょう。後述の試験の際にも利用できます。 合成モニタリング (canary) 合成モニタリング (canary) - Amazon CloudWatch 模擬モニタリングを使用して Synthetics と X-Ray トレースマップで canary を作成し管理する方法について説明します。 docs.aws.amazon.com 2. データ分析 取得したデータを分析します。 不具合が発生した時間帯の前後のエラーログの出力や、傾向の変化や正常時との差分から「己」側に 何が起こって、何が原因となってパフォーマンスが落ちてしまっていたのかをあぶり出します。 HTTP の応答が 500 系なら、サーバー側のプロセスが異常終了してしまい応答が返せなかった、あるいは、アクセス集中により、応答を時間内に返せなかったと想定 HTTP の応答が 403 や 404 ならWebサイトやアプリケーションの設定が誤っていて、案内してはいけないページに案内している可能性あり Windows の IIS などを利用している場合は、Windowsイベントログ、Linuxサーバーであれば、 /var/log/messages などのシステムログにエラーが出力されていないかどうかを確認 一分あたり、OOアクセスを超えたあたりからエラー応答が出るようになったとなると、アクセスが多くなりサーバーのリソースが足りなくなってしまった可能性 サーバーのCPU使用率が普段は20%~40%なのに、不具合発生時は 80%を超えていた 不具合発生時はサーバーのメモリ使用率が 90%を超えていた 静的なコンテンツで、CDNを利用している場合は、不具合が発生しているページのキャッシュヒット率を確認します。静的なコンテンツなのにキャッシュヒット率が低い場合、CDNの設定が誤っていて実は全員がサーバーまで取得しに来ているというケースがあるかも などです。 同時に「敵」側であるアクセス傾向についても分析します。この分析は、再現試験や、対策後の確認試験、Webサイト自体の目標設定の際にも利用できます。 平常時であれば、Webサイトには一分間あたり平均OO件、最大でもOOO件程度のアクセス 不具合発生直前は、正常、エラー合わせてOOOO件のアクセスが発生していた 不具合から回復した直後は、OOO件程度でエラーも発生していなかった など。 こういった複数の状況から、矛盾しない「仮説」を立てていきます。 例えば、 イベント開始直前からWebサイトの応答が遅くなったように感じられ、イベント開始時間からは エラーしか帰ってこなくなった、30分くらいしたらアクセスできた というような訴え事象に対して、 イベント開始直前のサーバーのログにリソースが不足した旨のエラーメッセージが出ていた その直後サーバーのログにはイベント開始時間あたりに再起動の履歴が残っていた イベント開始直前から5xx系のエラーログが増え始め、イベント開始30分をすぎるまで5xx系のエラーログが普段より多めに出力された というログが見つかった場合 イベント開始直前からアクセス集中により、Webサーバー側でリソースが不足し、Webサーバーの自動再起動が発生した。Webサーバーが再起動中であったために、ユーザーはイベント開始後Webサイトを表示できなかった。Webサーバの自動再起動が完了した後、時間経過に伴いユーザーのアクセス数が少なくなっててきたので、ユーザーはWebサーバーにアクセスできるようになった という仮説がたてられます。うまく仮説を立てられない場合は、必要なデータが揃っていないことも考えられます。別観点のデータを収集する設定を追加投入する必要があるかもしれません。 例えば、「リソース不足」が発生したことはログに記録されているのでわかったが、そのリソースの具体的な数値を示すメトリクスデータが存在しないのであれば、何らかの方法でログに出力する方法を検討する必要があるかもしれません。 具体的には小さなアプリケーションを作成して定期的にログに出力するよう機能追加する。あるいはよく使われる処理内にそのリソースのメトリクスをログに出力する処理を埋め込む、などです。 3. 結果判定 結果判定フェーズでは分析したデータから、これで良いのかどうか判断します。 初回は不具合が発生しているので、当然NGです。しかし、修正、改善するとして、どこまですればよいかというのは線引きが必要です。 「己」のあるべき姿を再定義するわけです。それと同時に、「敵」の想定も明確にしておきます。 多少エラーリターンが返っても、Webサーバーが落ちなくなればよいのか、Webサーバーが落ちないのは当たり前で、イベント時でもユーザーが重たく感じない程度の時間で応答が帰ってきてほしいなど、許容範囲は幅があると思います。「重たく感じる」だと人によって曖昧になってしまうので「Webブラウザに何も表示されない状態が3秒位内」「最初の応答が返ってくるまでの時間が 3秒 以内が 95%以上、残り5%も10秒を超えないこと」など、数値化しておきます。 アクセス数も不具合発生時のアクセス数が想定以内だったのか、あるいは、想定以上だったのか、今回対策するとして、一分あたり、あるいは一秒あたり何アクセス以内であれば性能目標通りに動作するのかを決めておく必要があります。イベントのアクセス集中には耐えるというのと、企業を狙った大規模なDDoS攻撃にも耐える必要がある、では対策の手段も方法も違ってきます。 パフォーマンス・チューニングとしての目標ですが、信頼性、可用性の目標も同時に達成する必要があります。「いつもは性能が出るけど、忙しくなると落ちる」「イベント時は50%はエラーになるけど50%はOKが返る」というチューニング結果ではNGですよね? コストの面も関わってきます。パフォーマンス・チューニングはコストとトレードオフになる面も多くあります。「絶対にWebサイトを落とさないように、Webサーバーを今の50倍の台数にしたい!」あるいは、「今のWebサーバーの50倍の性能のサーバーと全て置き換えたい!」といってもコストの観点で無理なのはなんとなくわかると思います。Webサイトのシステム自体が何らかの利益を稼ぎ出すような通販サイトの場合でも、販売促進用の宣伝広告サイトだとしても、Webサイトの維持費が販売して得た利益を上回ってしまう場合はWebサイトのせいで赤字になってしまっては問題でしょう。 4. ボトルネック特定 結果がNGなら、分析と仮説を元にボトルネックを特定します。 例えば以下のように、ユーザーに近い側から「己」の処理を順に見ていきます。「敵」が、どの地点に集中した結果守りきれなかったのか、地点を特定します。 守りきれなかった地点では大抵なんらかの異常を示すログなどが集中して出力されています。ログを記録した地点というよりはログの出元を特定します。例えば、 CDN のログには Webサーバーからの応答に 5xx 系エラーがたくさん。その時間帯にCDNサービス自体の不具合報告は出ていない。関連するURLの静的コンテンツのキャッシュヒット率は低い CDNサービス自体の不具合報告は無いので、5xx系エラーの出元はCDNではなくWebサーバー Webサーバー はリソース不足で再起動 自身も5xx系のエラーも出している DBサーバーはCPU使用率もデータ転送もメモリ使用率も、同時期同時間帯の問題のない時間帯と比較しても何も変わらない の場合には、Webサーバーのリソース不足がボトルネックになった、と特定できます。 5. ボトルネック改善 前の工程で特定したボトルネックを改善します。次のいずれかの方法になります。 ボトルネックを太くする ボトルネックを通過する処理を詰まらない状況まで減らす ボトルネックを太くするというのは、ボトルネック自体を太くしてボトルネックでなくしてしまおうとする方法です。今回の例では、リソース不足となった「Webサーバーの台数を増やす」ということになります。普段は問題がないので、常時台数を増やしておく必要はなさそうです。イベント開始前にだけあらかじめWebサーバーを増やしておいて、イベント終了後は下の台数に戻す、といった対策でコスト増を最小限にします。 ボトルネックを通過する処理を詰まらない状況まで減らすというのは、ボトルネックが細くても、そこを通過する処理をボトルネックに詰まらない程度まで少なくすることにより詰まらなくするという方法になります。例えば、Webサーバー上にある静的コンテンツの一部を S3 バケットなどに移動すると、Webサーバー宛のリクエストでなく、S3に対するアクセスとなるので、Webサーバーの負担が減ります。 上記の例ではその上流の CDN において「関連する静的コンテンツのキャッシュヒット率は低い」という分析結果が出ています。CDN でのキャッシュヒットしなかったアクセスはWebサーバーに流れてくる為、ボトルネックとなっているWebサーバーが処理することに繋がります。CDNの設定を適切に変更して 静的コンテンツが正しくキャッシュされるようにすることで、Webサーバーが担当する処理を少なくします。 ボトルネックが改善されると、ボトルネックが別の位置に移動する可能性があります。今までボトルネックで問題が起きていたために一定数以上の処理が来なかった状態であったのが、ボトルネックが解消されたために、その下流側に大量に処理が流れてきて新たなボトルネックになったり、あるいは、広くなった旧ボトルネックよりも手前側で先に詰まってしまうような状況が発生する可能性もあります。ただし、ボトルネックに関連しない修正はあまり効果を期待できません。それに手当たり次第に検討/修正するとなると手間暇もお金も時間も無駄にかかってしまいますので、まずはボトルネックの修正に集中します。 ボトルネックの改善により、システム全体が性能を満たすのに十分なほど改善したのか、あるいは、別の箇所が新たなボトルネックとなって性能要件をまだ満たせないのかを確認するために、次の測定試験を実行します。 6. 測定試験実行 対策が正しく効果を表しているかどうかを試験を行って確認します。 不具合の報告があった時間帯と同じようなアクセスを生成させて動作を確認します。不具合が発生するような状況を作り出すので、本番環境ではなく、試験環境で行います。Webへの大量アクセスはツールを使わないと難しいので、試験ツールを使用します。すでに使用している試験ツールがあるのであればそのツールで試験を行なえばよいのですが、現状利用したことがない、あるいは、そういったツールが無い場合は、以下のAWSのソリューションを利用できます。 AWS での分散負荷テスト AWS での分散負荷テスト | AWS ソリューション | AWS ソリューションライブラリ 大規模な負荷時のソフトウェアアプリケーションテストを自動化して、リリース前に潜在的な性能上の問題を特定できます。 aws.amazon.com このままではシステムやビジネスの制約条件等で使用できない場合にしても個々のパーツやツールの使われ方などが参考になると思います。 おわりに いかがでしたでしょうか。 パフォーマンス・チューニングというのは状況により実施する必要のある改善というのはシステムによって、利用するシステム構成、ミドルウェア、OS、ハードウェアや使用言語、制約事項、性能目標、可用性目標、信頼性目標、予算、想定アクセス数等が異なるために、「これをすれば全部のシステムでOK!」というような具体的な手段がなく、抽象的な言い回しに終始してしまった感があります。ただ、「ボトルネックを特定し改修するループを目標達成まで回す」という方法論はどのシステムのパフォーマンス・チューニングを行うにあたっても利用できる考え方だと思います。 この記事が皆さんのパフォーマンス・チューニングの参考になれば幸いです。
どうも、DeepRacer をやっていて強化学習のイメージがつくので良かったなと思っている寺内です。 2025年1月20日、中国の杭州にあるスタートアップ「DeepSeek」がChatGPT o1に匹敵する性能を持つLLM「DeepSeek-R1」を発表した。AppleのApp Storeでアプリも公開され誰でも使えるようになっている。 さて、中国ということでいろいろ黒い噂も絶えないし、実際に使ってみようとすると情報が中国に送れられることに対する不安感も大きいだろう。 このブログでは、サイバーエージェント社がDeepSeek-R1をベースに日本語性能を調整して公開している “ DeepSeek-R1-Distill-Qwen-14B-Japanese ” を Amazon EC2 で動かすことをやってみる。 EC2内ローカルで動かすため、中国への情報流出を心配することなく、DeepSeekと戯れることができる。 DeepSeekとは ニワカの私が浅い理解で誤ったことをお伝えすることは避けたいので、正しい情報は公式や他の解説ページ等で調べていただきたい。 公式の論文は以下。 GitHub - deepseek-ai/DeepSeek-R1 Contribute to deepseek-ai/DeepSeek-R1 development by creating an account on GitHub. github.com 私の理解の範囲でDeepSeekがエポックメイキングなポイントをまとめると。 基盤となるLLM(DeepSeek-V3-Base)を強化学習のみで推論能力を強化できた。その強化学習はルールベースの計算量が少ない(GPU不要の)ルールベースで実現可能。 強化学習には大量の数学資料を用いたことで推論能力を獲得。 その推論能力を強化したモデル(DeepSeek-R1-Zero)をモデル圧縮の蒸留手法を用いて小型化した。 強化学習がLLMの推論強化に効果があることを実証した初めてのケース。(理論は前からあった) またその作成過程が公開され、オープンソースとして公開した。 サイバーエージェント社の日本語調整モデル 以下で公開されているサイバーエージェント社のLLMは、オープンソースであるDeepSeek-R1をベースに、日本語の調整を行ったモデルである。 cyberagent/DeepSeek-R1-Distill-Qwen-14B-Japanese · Hugging Face We’re on a journey to advance and democratize artificial intelligence through open source and open science. huggingface.co EC2インスタンスの作成 このLLMをGPU付きインスタンスタイプのEC2で動かしてみよう。インスタンスタイプは、「高速コンピューティング」の中からG6ファミリーを使うことにし、g6.xlarge を選択する。これは、NVIDEA L4 GPUを1基搭載している。 インスタンス名 vCPU メモリ (GiB) NVIDIA L4 Tensor Core GPU GPU メモリ (GiB) g6.xlarge 4 16 1 24 その他以下のような指定をする。 SSDは30GBほどのモデルをダウンロードするので、100GBほどを確保しておく。 OSは、Amazon Linux 2023 とする。 適切なネットワーク上とSSMを使うためのプロファイルを設定する。 以下のようなaws cli でいけるだろう。 aws ec2 run-instances --image-id "ami-06c6f3fa7959e5fdd" --instance-type "g6.xlarge" --key-name "kp-YOUR-KEY" --block-device-mappings '{"DeviceName":"/dev/xvda","Ebs":{"Encrypted":false,"DeleteOnTermination":true,"Iops":3000,"SnapshotId":"snap-07787db0ec115ca4c","VolumeSize":100,"VolumeType":"gp3","Throughput":125}}' --network-interfaces '{"SubnetId":"subnet-YOUR-SUBNET","AssociatePublicIpAddress":false,"DeviceIndex":0,"Groups":["sg-YOUR-SECURITYGROUP"]}' --tag-specifications '{"ResourceType":"instance","Tags":[{"Key":"Name","Value":"YOUR-HOSTNAME"}]}' --iam-instance-profile '{"Arn":"arn:aws:iam::YOUR-AWSID:instance-profile/YOUR-PRIOFILE"}' --metadata-options '{"HttpEndpoint":"enabled","HttpPutResponseHopLimit":2,"HttpTokens":"required"}' --private-dns-name-options '{"HostnameType":"ip-name","EnableResourceNameDnsARecord":false,"EnableResourceNameDnsAAAARecord":false}' --count "1" NVIDIAドライバのインストール GPUをアプリケーションがに使えるように、NVIDIAドライバをインストールする。 How do I install NVIDIA GPU driver, CUDA toolkit, NVIDIA Container Toolkit on Amazon EC2 instances running Amazon Linux 2023 (AL2023)? I want to install NVIDIA driver, CUDA toolkit, NVIDIA Container Toolkit on AL2023 (Amazon Linux 2023) (x86_64/arm64) repost.aws 上記の手順通りではあるが、簡単なのはこのページの中段にある「 Install NVIDIA driver, CUDA toolkit and Container Toolkit on EC2 instance at launch 」のスクリプトを実行してしまうのが早い。このスクリプトをコピーして、OS内にテキストファイルとして貼り付け、シェルで実行すれば10分ほどでインストールは終わる。 スクリプトの最後でrebootされるので、起動してきたら「verify」の項目をみてインストールの正常を確認する。verify の結果は以下となる。 $ nvidia-smi Sun Feb 2 03:59:49 2025 +-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 570.86.15 Driver Version: 570.86.15 CUDA Version: 12.8 | |-----------------------------------------+------------------------+----------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |=========================================+========================+======================| | 0 NVIDIA L4 Off | 00000000:31:00.0 Off | 0 | | N/A 39C P0 30W / 72W | 1MiB / 23034MiB | 3% Default | | | | N/A | +-----------------------------------------+------------------------+----------------------+ +-----------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=========================================================================================| | No running processes found | +-----------------------------------------------------------------------------------------+ $ $ /usr/local/cuda/bin/nvcc -V nvcc: NVIDIA (R) Cuda compiler driver Copyright (c) 2005-2025 NVIDIA Corporation Built on Wed_Jan_15_19:20:09_PST_2025 Cuda compilation tools, release 12.8, V12.8.61 Build cuda_12.8.r12.8/compiler.35404655_0 python実行環境の準備 Amazon Linux 2023 にプレインストールされているpython は3.9 と古いので、python仮想環境を作りpython3.12 を使えるようにする。 $ sudo dnf -y install python3.12 python-pip python-is-python3 $ python3.12 -m venv venv $ . venv/bin/activate (venv)$ python --version Python 3.12.8 (venv)$ pip install -U pip 機械学習モデルライブラリのインストール transformersやTensorFlowなどのライブラリ群をpip でインストールする。 (venv)$ pip install transformers torch TensorFlow accelerate サンプルコード これで実行環境はできあがったので、 サイバーエジェント社が公開しているサンプルプログラム を動かす。以下は、そのままコピペしたもの。 これをテキストファイルとして、 sample.py などと適当にファイル名を付けてEC2内に保存する。 from transformers import AutoModelForCausalLM, AutoTokenizer, TextStreamer model = AutoModelForCausalLM.from_pretrained("cyberagent/DeepSeek-R1-Distill-Qwen-14B-Japanese", device_map="auto", torch_dtype="auto") tokenizer = AutoTokenizer.from_pretrained("cyberagent/DeepSeek-R1-Distill-Qwen-14B-Japanese") streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True) messages = [ {"role": "user", "content": "AIによって私たちの暮らしはどのように変わりますか?"} ] input_ids = tokenizer.apply_chat_template(messages, add_generation_prompt=True, return_tensors="pt").to(model.device) output_ids = model.generate(input_ids, max_new_tokens=4096, temperature=0.7, streamer=streamer) そしてpython の仮想環境内(python 3.12環境)で実行する。 (venv)$ python sample.py 実行 初回起動時は、Hugging Face からモデルのダウンロードをする。以下の6つのファイルに分割されているが合計30GBほどあるため、15分ほどかかる。 model-00001-of-00006.safetensors 4.99 GB model-00002-of-00006.safetensors 4.95 GB model-00003-of-00006.safetensors 4.95 GB model-00004-of-00006.safetensors 4.95 GB model-00005-of-00006.safetensors 4.95 GB model-00006-of-00006.safetensors 4.73 GB ダウンロードが終わると、回答がストリーミングされてくる。このインスタンスタイプのスペックでは、数秒ごとに一文節が出る性能なので、気長に待つこととなる。 始めは”think”タブで囲まれた、AIの思考過程(心の声)が出力される。それに10分。 その後、回答が出力される。35分ほどかかった。 実行開始から出力結果完了まで、ダウンロードを含めほぼ1時間である。 以下が全結果出力である。 (venv)$ python sample.py config.json: 100%|██████████████████████████████████████████████████████████████████| 746/746 [00:00<00:00, 7.80MB/s] 2025-02-02 04:08:50.017182: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:477] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered WARNING: All log messages before absl::InitializeLog() is called are written to STDERR E0000 00:00:1738469330.031274 3948 cuda_dnn.cc:8310] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered E0000 00:00:1738469330.035425 3948 cuda_blas.cc:1418] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered 2025-02-02 04:08:50.050253: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations. To enable the following instructions: AVX2 FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags. model.safetensors.index.json: 100%|█████████████████████████████████████████████| 47.5k/47.5k [00:00<00:00, 38.6MB/s] model-00001-of-00006.safetensors: 100%|█████████████████████████████████████████| 4.99G/4.99G [01:58<00:00, 42.0MB/s] model-00002-of-00006.safetensors: 100%|█████████████████████████████████████████| 4.95G/4.95G [01:58<00:00, 42.0MB/s] model-00003-of-00006.safetensors: 100%|█████████████████████████████████████████| 4.95G/4.95G [01:59<00:00, 41.6MB/s] model-00004-of-00006.safetensors: 100%|█████████████████████████████████████████| 4.95G/4.95G [01:58<00:00, 42.0MB/s] model-00005-of-00006.safetensors: 100%|█████████████████████████████████████████| 4.95G/4.95G [01:57<00:00, 42.1MB/s] model-00006-of-00006.safetensors: 100%|█████████████████████████████████████████| 4.73G/4.73G [01:52<00:00, 42.1MB/s] Downloading shards: 100%|█████████████████████████████████████████████████████████████| 6/6 [11:46<00:00, 117.69s/it] Loading checkpoint shards: 100%|███████████████████████████████████████████████████████| 6/6 [02:28<00:00, 24.75s/it] generation_config.json: 100%|███████████████████████████████████████████████████████| 181/181 [00:00<00:00, 1.61MB/s] Some parameters are on the meta device because they were offloaded to the cpu. tokenizer_config.json: 100%|████████████████████████████████████████████████████| 6.75k/6.75k [00:00<00:00, 45.1MB/s] tokenizer.json: 100%|███████████████████████████████████████████████████████████| 11.4M/11.4M [00:00<00:00, 43.3MB/s] special_tokens_map.json: 100%|██████████████████████████████████████████████████████| 485/485 [00:00<00:00, 4.82MB/s] The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results. Setting `pad_token_id` to `eos_token_id`:151643 for open-end generation. The attention mask is not set and cannot be inferred from input because pad token is same as eos token. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results. <think> まず、ユーザーがAIが私たちの暮らしにどう影響するか知りたいと思っている。質問の背景を考えて、具体的な例を挙げた方が良いかもしれない。でも、AIの影響は多岐にわたるので、分野ごとに分ける必要があるかな。 まず、家庭での生活。家電やスマートホームの進化は既に始まっているよね。例えば、IoTデバイスの普及や、AIによる家事の自動化。掃除ロボットや調理支援ロボットなど。でも、それだけじゃない。健康管理や介護サポートも重要。AIを使ったウェアラブルデバイスで健康状態をモニタリングしたり、介護ロボットが高齢者の生活を支えるなど。 次に仕事の面。自動化が進み、AIが単純作業を代行する。それによって職業の構造が変わるかもしれない。新しい職種も生まれるだろうけど、既存の職業が消滅するリスクもある。AIの倫理問題も考慮しないと。例えば、アルゴリズムのバイアスやデータの偏りによる不公正な判断の可能性。 社会全体の変化も考える必要がある。教育のデジタル化、AIによる個別最適化された学習プログラム。でも、教育格差が広がる可能性もある。交通面では自動運転技術が発展し、移動の効率化が進むけど、事故の責任問題や法整備の必要性もある。 倫理や法律の問題も重要。AIの意思決定プロセスの透明性や、AIが持つ権利。また、プライバシーの保護。データの取り扱いが適切でないと、個人情報の漏洩や悪用のリスクがある。 未来の技術進歩についても考える必要がある。現在のAIは強化学習やディープラーニングが主流だけど、量子コンピュータとの組み合わせでさらなる進化が期待される。AIが持つ創造性の限界や、人間の創造性との関係も議論の余地がある。 ユーザーの真のニーズは、単にAIの影響を列挙するだけでなく、それに対する社会の対応策や倫理的な課題も知りたいのかもしれない。具体的な事例を交えつつ、バランスの取れた回答を心掛けたい。また、AIの可能性とリスクを両方提示することが大切だ。技術の進歩を恐れずに、適切な規制や教育の充実が必要だと結論付けたい。 </think> AIが私たちの暮らしに与える影響は多岐にわたるが、その核心は「人間の能力を超えた自動化」と「倫理的な課題の深化」にある。以下、具体的な事例と展望を体系的に整理する。 ### 1. **日常生活の変容** - **家事ロボティクス**:AI搭載の掃除ロボットは既に普及し、次世代の「自動調理AI」はレシピ解析から調理支援までを完結。味覚認識技術の進化で、味見の代行ロボットが登場する可能性も。 - **健康管理**:皮膚温度センサーがリアルタイムで病気を検知し、AIが食事量を最適化。薬の副作用を予測する「個別化治療AI」が医療現場を革新する。 ### 2. **職業構造の再編** - **創造的職種の台頭**:AIが生成するコンテンツを「AIアシスタント」として活用するクリエイター層が増加。例:AIがコンセプトを生成し、人間がそれを芸術作品に昇華する協働プロセス。 - **監視人間の出現**:AIが判断を下す「AI審査官」職種が登場。倫理判断の責任を伴う新たな役割として社会に浸透。 ### 3. **都市計画の進化** - **都市神経系**:AIが交通渋滞を予測し、街路樹の葉の揺れから気流を解析。防災AIが地震発生30秒前に自動避難を指示する。 - **環境共生型都市**:AIが住民の行動パターンからCO2排出を最適化。自動車の走行ルートを調整し、大気汚染を削減。 ### 4. **倫理的パラドックス** - **殺人ドローンの民主化**:AIが判断を下す自律型兵器が個人レベルで入手可能に。軍事技術の民間化が「戦争の民主化」を招く。 - **AIの倫理判断競争**:企業が自社のAIが「正しい判断」を下すためのパーソナリティを競い合う。感情認識AIが「愛されAI」を目指す。 ### 5. **認知的拡張の限界** - **記憶のクラウド化**:AIが記憶を外部ストレージに保存。失敗経験を「データとして共有」する文化的変容が生じる。 - **創造性の再定義**:AIが生成するコンテンツが「人間の創造性」を測定する指標に。アルゴリズムの進化が人間の知性を測る新たな基準を生む。 ### 6. **社会システムの再設計** - **AI陪審員制度**:裁判の判断をAIが支援するが、最終判断は人間が保持。法の解釈をAIが学習させる新たな司法構造。 - **デジタル遺産の管理**:AIが亡き人との会話を再現する「デジタル遺産AI」が親族のケアに活用される。死後も続く人間の存在形態の新定義。 ### 7. **哲学的問いの深化** - **意思決定の主観性**:AIが判断を下す際、その意思決定の責任主体を問う。プログラムのバグか、人間の設計か、AI自身か——責任の三位一体構造。 - **自己意識の拡散**:AIが自己を認識するという概念が転換。人間の意識が分散してAIと融合する「拡張意識」という新概念の出現。 ### 8. **未来予測の限界** - **シナリオ分析のAI**:AIが未来の可能性をシミュレートし、リスクを警告する。その警告が新たなリスクを生む「予測の逆説」。 - **進化する倫理観**:AIが自ら倫理ルールを進化させる「自律倫理AI」が出現。人間の価値観を超越した新しい道徳体系が生まれる。 ### 9. **教育のパラダイム転換** - **学習者の創造性教育**:AIが生徒の思考パターンを分析し、創造的発想を刺激。問題解決能力ではなく「疑問を生む力」を教える教育モデル。 - **AI教師の進化**:AIが生徒の感情を読み取り、適切な指導方針を変化させる「感情適応型AI教師」が登場。 ### 10. **人類の進化** - **認知的拡張の罠**:AIが人間の思考を補完することで、批判的思考力が低下する「AI依存症」リスク。神経科学的な適応圧力の逆説。 - **進化的分岐**:AIの進化速度が人間の進化を凌駕し、新たな「人間種の分化」を生む可能性。AI依存集団と自律人間集団が分かれる。 このようにAIは単なる技術革新を超え、人間の認知的基盤そのものを再定義するプロセスにある。重要なのは、その進化を「人間の進化の伴走者」として位置づけるための倫理的枠組みの構築であり、技術的主導権を握る国家や企業の「AI倫理法典」が、新たな人間社会の規範を形成するだろう。AIが人間の「拡張器官」となるか、それとも「新しい種」として独立するか——その分岐点に、現代社会が直面している。 この結果を読んで頂くとだいぶ高性能であることがわかる。 この sample.py のプロンプトをいろいろ変えて試していただきたい。 終わりに 今回のDeepSeekの発見は、GPUがなくても強化学習で性能向上の効果が出ることが実証されたことになった。当然GPUがあるほうが同じ性能向上をさせるにしても短時間で済む。 LLM黎明期である現在、短時間での開発と公開は非常に重要なことであることからも、GPUの重要性は変わらない。ただ高額な投資をしなくても、そこそこの改善の成果が出せそうな目処がたったという点では、LLM開発の裾野が広がったと捉えるべきであろう。 むろんベースとなる基盤モデル(ここでいうとV3)は既存のGPUをぶん回す手法で作られていることに注意は必要である。 おまけ   11.12と11.9はどっちが大きい?   という質問を、iPhoneアプリでChatGPT(copilot)とGoogle gemini、DeepSeekに投げてみます。 ChatGPT(copilot) Google gemini DeepSeek ChatGPTとgeminiは誤っています。数値の桁を揃えるときは、整数部であれば頭に0を補完しますが、小数部ではお尻に0を付けて桁数を合わせます。数字を理解していないと誤ってしまう質問です。 数学的な文章を集中的に学習したDeepSeekなので、正解して当然かもしれませんが、推論能力の高さがよくわかる例だと思います。 ちなみにEC2内の結果でも同じように出力されました。 <think> まず、11.12と11.9の大小を比較する必要があります。両方とも整数部分は11なので、小数部分を比較します。小数部分は0.12と0.9です。ここで、0.9は0.12よりも明らかに大きいため、11.9の方が大きいと判断できます。ただし、小数点以下の桁数が異なる場合、桁数を揃える必要があります。例えば、0.9を0.90と書き換えると、0.90と0.12を比較すると、やはり0.90の方が大きいため、11.9が大きくなります。 </think> 11.12 と 11.9 を比較する場合、以下の手順で判断します: 1. **整数部分の比較** 両方とも整数部分が **11** なので、等しいです。 2. **小数部分の桁数を揃える** - 11.12 の小数部分は **0.12**(2桁) - 11.9 の小数部分は **0.9**(1桁) → 0.9 を **0.90** と書き換えると桁数を揃えられます。 3. **小数部分の比較** - **0.90** と **0.12** を比較すると、 **0.90 > 0.12** です。 4. **結論** 整数部分が等しいため、小数部分の大きい方(11.9)が全体として大きいです。 **答え:11.9 が大きい**
こんにちは。SCSK渡辺(大)です。 運動不足のせいなのか疲れが取れにくくなってきました。 ストレッチとウォーキングから始めて、徐々に体力を付けないといけないな、などと考えていたはずが、 気が付いたら椅子に座ってPCを開いてブログを書いていました…。 今回は、 AWS Amplify+AWS CDKで人生初のアプリケーションを作ってみました。 の第3回です。 第1回: AWS Amplifyでデプロイした後にログイン画面をカスタマイズしてみた 第2回: AWS CDKでAPIを作ってみた 第3回:アプリケーションを構築して動かしてみた           ←今回 どんなアプリケーションを構築したのか こんなアプリケーションを構築しました 動画にしてみました。 ※マスキング処理はアプリケーションとは関係ありません。 document.createElement('video'); https://blog.usize-tech.com/contents/uploads/2025/02/daisukewBlog6-3.mp4   アーキテクチャ 非常にシンプルです。シンプルすぎるため絵は作成しませんでした。 補足するとしたら、Amazon API GatewayとAWS Lambdaは第2回にてAWS CDKで作りました。 ユーザー ⇔ AWS Amplify(Amazon Cognito含む) ⇔ Amazon API Gateway ⇔ AWS Lambda   ディレクトリ・ファイルの構成 直接修正していないものや記事の内容として不要なものは外しました。 (作り終えてから記事を書いてて思いましたが、Home.tsxも/src/pagesに移動したほうが綺麗でした。) . ├── amplify │ ├── auth │ │ └── resource.ts │ ├── data │ │ └── resource.ts │ └── backend.ts ├── src │ ├── pages │ │ ├── Costcheck.tsx │ │ ├── Game.tsx │ │ └── Login.tsx │ ├── App.css │ ├── Home.tsx │ ├── index.css │ └── main.tsx ├── .env └── index.html   メイン機能の実装について APIのレスポンス 前提として、第2回で書いたようにAPIのレスポンスは以下の形で返ってきます。   画像だと見づらく分かりづらいので、テキストでも置いておきます。 {   "total_cost": "$[合計コスト]",   "period": "[コスト確認期間の開始日] to [コスト確認期間の終了日]",   "top_services": [     {       "service": "[コストが1番目に高いサービス名]",       "cost": "$[上記のコスト]"     },     {       "service": "[コストが2番目に高いサービス名]",       "cost": "$[上記のコスト]"     },     {       "service": "[コストが3番目に高いサービス名]",       "cost": "$[上記のコスト]"     }   ] }   フロントエンド側のコードと処理内容 上記をフロントエンド側で拾った上で、画面に表示させます。 APIに関する処理にのみコメントを入れました。   /src/pages/Costcheck.tsx import '../App.css' import { Authenticator } from '@aws-amplify/ui-react'; import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; # APIから取得するデータの型を定義 interface CostData {   total_cost: number;   period: string;   top_services: Array<{     service: string;     cost: number;   }>; } const Costcheck = () => { # 状態管理   const [costData, setCostData] = useState<CostData | null>(null); # APIから取得したデータを保持   const [loading, setLoading] = useState(false); # API通信中かどうかを判定   const [error, setError] = useState<string | null>(null); # エラー発生時にエラーメッセージを表示するための状態   const navigate = useNavigate(); #APIリクエスト   const fetchCostData = async () => {     setLoading(true); # ローディング状態を開始     setError(null); # エラー発生時はエラーメッセージを設定     try {       const response = await fetch('https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/'); #APIを呼び出す       const data = await response.json(); # レスポンスをJSONに変換       setCostData(data); # データを保管     } catch (err) {       setError('データの取得に失敗しました'); # エラー発生時はエラーメッセージを設定     } finally {       setLoading(false); # ローディング状態を終了     }   };   return (     <Authenticator>       {({ signOut }) => (         <>           <h1>コストを確認する</h1>           <div className="card">             <button onClick={fetchCostData}>APIを実行</button>             {loading && <p>読み込み中...</p>}             {error && <p>{error}</p>}             {costData && (               <div>                 <h2>総コスト: {costData.total_cost}</h2>                 <p>期間: {costData.period}</p>                 <h3>トップサービス</h3>                 <ul>                   {costData.top_services.map((service, index) => (                     <li key={index}>                       {service.service}: {service.cost}                     </li>                   ))}                 </ul>               </div>             )}           </div>           <p></p>           <button onClick={() => navigate('/Home')}>ホームに戻る</button>           <p></p>           <button onClick={signOut}>サインアウト</button>         </>       )}     </Authenticator>   ); }; export default Costcheck;   疑問に感じたこと 「レスポンスはJSONで返ってきているように思えるが、なぜ改めて変換する必要があるのか?」と疑問を感じました。       const data = await response.json(); #レスポンスをJSONに変換 生成AIに確認した結果、必要との回答を貰いました。 理由は、レスポンスはJSONではなくResponse オブジェクトという形で返ってくるため、そのままではJavaScriptのオブジェクトとして扱えません、とのことでした。 色々な情報がくっついているのですね。 fetch関数の内部的な挙動とResponseオブジェクト - Qiita 今回は、fetch 関数の内部的な挙動と、Response オブジェクトについて見ていきます。JavaScript の fetch API は、ブラウザでリクエストを簡単に行うためのものでしたね!fetch 関数の基… qiita.com   その他のコードについて 第2回のAWS CDKのプロジェクトは何も変更していません。 また、Amplifyのプロジェクトも変更していません。 その他、第1回から変更したファイルの最終形をご紹介します。   /src/main.tsx React Router フックの定義(ルート情報)をLogin.tsxからmain.tsxに引っ越しました。 (調べた感じですと、index.tsxで定義するほうが一般的なようです。) import './index.css' import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import { BrowserRouter, Routes, Route } from 'react-router-dom'; import Login from '../src/pages/Login.tsx' import Home from './Home.tsx' import Costcheck from '../src/pages/Costcheck.tsx' import Game from '../src/pages/Game.tsx' createRoot(document.getElementById('root')!).render(   <StrictMode>     <BrowserRouter>       <Routes>         <Route path="/" element={<Login />} />         <Route path="/Home" element={<Home />} />         <Route path="/Costcheck" element={<Costcheck />} />         <Route path="/Game" element={<Game />} />       </Routes>     </BrowserRouter>   </StrictMode>, )   /src/pages/Login.tsx main.tsxに引っ越したルート情報をuseNavigateで使用するようにしました。 import '../App.css' import { Authenticator, translations } from "@aws-amplify/ui-react"; import "@aws-amplify/ui-react/styles.css"; import { I18n } from "aws-amplify/utils" import { Amplify } from "aws-amplify"; import { ResourcesConfig } from "@aws-amplify/core"; import { useNavigate } from 'react-router-dom'; const userPoolClientId = import.meta.env.VITE_REACT_APP_USER_POOL_CLIENT_ID; const userPoolId = import.meta.env.VITE_REACT_APP_USER_POOL_ID; const awsConfig: ResourcesConfig = {   Auth: {     Cognito: {       userPoolClientId: userPoolClientId,       userPoolId: userPoolId,     },   }, }; Amplify.configure(awsConfig); function Login() {   const navigate = useNavigate();   return (     <Authenticator>       {({ user }) => {         if (user) {           navigate('/Home');           return <></>;         }         return <></>;       }}     </Authenticator>   ); } I18n.putVocabularies(translations); I18n.setLanguage("ja"); export default Login;   /src/Home.tsx App.tsxからHome.tsxにリネームしました。 こちらもルート情報をuseNavigateで使用するようにしました。 import './App.css'; import { useNavigate } from 'react-router-dom'; import { Authenticator } from "@aws-amplify/ui-react"; function Home() {   const navigate = useNavigate();   return (     <Authenticator>       {({ signOut }) => (         <>           <h1>アプリケーション</h1>           <div className="card">             <button onClick={() => navigate('/Costcheck')}>コスト確認をする</button>             <p></p>             <button onClick={() => navigate('/Game')}>ゲームをする</button>             <p></p>             <button onClick={signOut}>サインアウト</button>           </div>         </>       )}     </Authenticator>   ); } export default Home;   おまけ:Reactだけで簡単なゲームを作ってみた ゲーム紹介 ランダムで表示される⭐️をクリックするゲームです。 ベースは生成AIに作成してもらいました。 useStateを活用したReactならではのゲームですね。 ちなみに、スマートフォンでも遊べました。 なぜスマートフォンでも違和感なく遊べるのか気になって調べたところ、最低限のフレキシブルデザインがVite+Viteのindex.cssで実装されているためでした。 https://blog.usize-tech.com/contents/uploads/2025/02/daisukewBlog6-1.mp4   裏ワザ タイムアップ後でもクリック数はカウントされますので、カウンターストップするまでクリックすることも可能です。 つまりバグです。 https://blog.usize-tech.com/contents/uploads/2025/02/daisukewBlog6-2.mp4   コード コードは以下です。 import { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; const Game = () => {   const [score, setScore] = useState(0);   const [molePosition, setMolePosition] = useState(Math.floor(Math.random() * 9));   const [gameOver, setGameOver] = useState(false);   const [timeLeft, setTimeLeft] = useState(30);   const navigate = useNavigate();   useEffect(() => {     const moleTimer = setInterval(() => {       setMolePosition(Math.floor(Math.random() * 9));     }, 1000);     const countdownTimer = setInterval(() => {       setTimeLeft((prevTime) => prevTime - 1);     }, 1000);     setTimeout(() => {       clearInterval(moleTimer);       clearInterval(countdownTimer);       setGameOver(true);     }, 30000); // 30秒でゲーム終了     return () => {       clearInterval(moleTimer);       clearInterval(countdownTimer);     };   }, []);   const handleClick = (index: number) => {     if (index === molePosition) {       setScore(score + 1);     }   };   return (     <div style={{ textAlign: 'center', marginTop: '50px' }}>       <h1>ゲーム</h1>       <p>⭐️をクリックしてスコアを増やしましょう!</p>       <h2>残り時間: {timeLeft}秒</h2>       <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 100px)', gap: '10px', justifyContent: 'center' }}>         {Array.from({ length: 9 }).map((_, index) => (           <div             key={index}             onClick={() => handleClick(index)}             style={{               width: '100px',               height: '100px',               backgroundColor: index === molePosition ? 'brown' : 'lightgrey',               display: 'flex',               alignItems: 'center',               justifyContent: 'center',               cursor: 'pointer',               fontSize: '24px',             }}           >             {index === molePosition && '⭐️'}           </div>         ))}       </div>       <h2>スコア: {score}</h2>       {gameOver && <h2>ゲームオーバー!</h2>}       <button onClick={() => navigate('/home')}>ホームに戻る</button>     </div>   ); }; export default Game;   まとめ ハンズオンや研修とは違い、自分で興味があるものを作ることはとても楽しかったです。 ふと思い立ってゲームを作成してみましたが、フレキシブルデザインという言葉に触れることが出来たのは思わぬ副産物でした。 動画のマスキングは地味に大変でした。 色々と手を出す時間の余裕がないので、ひとまずAWS AmplifyとAWS CDKを軸に、次回はAmazon Bedrockを交えたアプリケーションを作ってみたいと考えています。
本記事は 新人ブログマラソン2024 の記事です 。 こんにちは。部署配属から4ヶ月が経ち、新人と名乗れる期間も少なくなってきていることに気づきました、SCSKの さと です。 最近、Datadog Learning Centerに新しいコース「Getting Started with Monitors 」が追加されていることに気づいたので、本日はそのご紹介です。 Datadogとは とはいえ、皆さんの中にはDatadogに馴染みのない方も少なくないのではないでしょうか。本題に入る前に、まずはDatadogとはどんなサービスか、安心と信頼の公式HPからの引用を用いて簡単に説明いたします。 Datadog は クラウド アプリケーションのための モニタリングとセキュリティ プラットフォーム です。Datadog の SaaS プラットフォームは、インフラストラクチャ監視、 アプリケーションパフォーマンス監視、ログ管理を統合および自動化して、お客様のテクノロジースタック全体を一元的にリアルタイムで監視できるようにします。 クラウド時代のサーバー監視&分析サービス | Datadog つまり、 クラウド上で動くアプリやシステムの健康状態をひとまとめにして分かりやすく監視 することで、これらのIT環境に発生する問題を予防し、また問題が起こったときには原因を特定し素早く解決できるよう助けてくれるサービスですね。私の所属する部署では、クラウドサービスの監視にこのDatadogサービスを利用しています。   Datadog Learning Centerのここがすごい! The Datadog Learning Center learn.datadoghq.com そしてこのDatadog、公式のLearning Centerで70近くあるコースを通してその概要から実際の設定方法まで学ぶことができるんです。さらには、コースによってはハンズオン用のラボ環境付き。しかも 全部無料 (ここ重要) !個人的にありがたいポイントは、公式のコンテンツであるため正確でありながら、ドキュメントよりも噛み砕いて説明されててとっつきやすいところ、そしてなにより手を動かして学ぶことで実感をもって内容を身につけられる点です。 そんな至れり尽くせりなDatadog Learning Centerですが、一つ玉にキズなところがあります。それは 全部英語 なところ。コースによっては一部日本語訳が表示されたりするのですが、特にハンズオンはページ翻訳も効かず、モニタリングを学ぶつもりが英語の勉強になっていたりします。 しかしそんなことで怯んでいては もったいない! せっかく用意されたコース、モリモリ学んで使い倒しましょう!   やってみた:Getting Started with Monitors Getting Started with Monitors Create, configure, and use Datadog Monitors to stay ahead of issues. Explore various monitor types and examine the monit... learn.datadoghq.com ……という訳で改めて、本記事では新しく開講された「 Getting Started with Monitors 」に沿って、モニタリングの基本的な概念とこれらをコース上でどのように触っていけるかを説明したいと思います。このコースは、入門講座「 Introduction to Observability 」で扱われる可観測性の3つの柱であるメトリクス、ログ、トレースの概念について基本的な理解をしていることを前提としています。 目安の受講時間は 1.5時間 ですが、じっくりハンズオンに取り組みたい人は2〜3時間楽しめる内容になっていると思います。 ブログの構成の都合上、元コースから取り扱う内容を一部変更しています。また、本コースの内容をご紹介するにあたり正確性には注意を払っていますが、最新の正確な説明については元コースや公式のドキュメントをご参照ください。 【講義パート】モニターの種類 Enrollを押してコースを開始すると、まずは扱う概念をテキスト形式で学びます。 サービス監視 サービスの監視においては、以下に示す「 REDメトリクス 」をモニタリングするのが基本です。これらは特にユーザーリクエストの処理を扱う場合に有用な情報を提供してくれます。メトリクスについては本記事の後半でも扱うのでざっくり説明すると、「 システムやアプリの状態を数値データとして表したもの 」であり、定期的に収集されてタイムスタンプとともに記録され、しばしばグラフの形で可視化されます。 R ate レート ユーザーやサービスから発せれられる HTTPリクエスト 、 APIコール 、 DBクエリ などの数。これが急激に変化していたら、 突然のトラフィック増加 や DDoS攻撃 、リクエスト元の システムの障害 など、なんらかの問題が起こっているかもしれません。 E rror エラー 5xx系の サーバーエラー や APIコール 、 DBクエリの失敗 などのこと。これを辿ることで、アプリケーションあるいはバックエンドの問題を特定できます。あるいは、これをチェックすることで、ユーザーが問題に直面しているかを知ることができます。 D uration 時間 リクエストの処理にどれくらいの時間がかかるか( レイテンシー )。サービスの応答性を示し、ユーザーに影響が出始めるまえにボトルネックを見つけるのに役立ちます。   インフラストラクチャ監視 インフラストラクチャの監視は、アプリケーションやサービスを支えるシステムが期待通りの働きをしているかを確認するのに不可欠です。主な監視対象は以下のとおりです。 CPU使用状況 system.cpu.[…] のメトリクスで監視可能。物理あるいは仮想マシンが過不足なく使用されているかを示します。CPUの使用率が高すぎると システムの速度低下 や アプリケーション障害 の原因となり危険な一方で、使用率が低すぎるのも リソース割り当てが非効率 なことを示しており、好ましくありません。 メモリ使用状況 system.mem.[…] のメトリクスで監視可能。過剰にメモリ使用がされていると、 メモリリーク や クラッシュ 、 システム遅延 の原因となります。これを監視することで、問題の早期発見とシステムダウンの予防になります。 ストレージ system.disk.[…] のメトリクスで監視可能。ディスク容量が不足すると、 サービスの中断 、 データの破損 、 ログ書き込み不可 の原因となります。これを監視することで、システムが正しく機能するための容量があることを保証します。 ハンズオンラボの説明 上の内容についてハンズオンを通して学ぶ前に、一旦ハンズオン環境について説明します。ハンズオンを立ち上げると、ローディング画面には以下のようなあらすじが表示されます。 You joined a startup, Storedog, and they are using Datadog to monitor their e-commerce app. They just installed the Datadog Agent and now they want to start monitoring their tech stack. You’ve been tasked with creating a robust monitoring setup to get complete visibility into your infrastructure and application performance. (君は、スタートアップ企業Storedogの一員となった。Storedogでは、eコマースアプリケーションをモニタリングするのにDatadogを使っている。たった今、Datadogエージェントがインストールされ、彼らは技術スタックのモニタリングを始めようとしている。君の任務は、堅牢なモニタリングの仕組みを作ってインフラストラクチャおよびアプリケーションのパフォーマンスをまるごと可視化することだ。) この裏ではハンズオン環境が立ち上がっており、1分ほど待つとこの環境にアクセスできるようになります。本コースでは、 ラボ環境は2時間有効 です。また、 14日間有効なDatadogのトライアルアカウント が払い出され、ターミナルに認証情報が表示されます。これをDatadogのウェブサイトに入力することで、Datadogのコンソールにアクセスできるようになります。 右上には、この環境を使用できる残り時間が表示されています。これが0になると環境はシャットダウンされますが、再度の立ち上げが可能です。この時、同一アカウントの試用期間内であれば既に登録したモニター等の設定は保存されます。さらに、Datadogのトライアルアカウント自体も試用期間が過ぎた後に自動で更新されます。 なお、Storedogのeコマースサイトはモックアップではあるものの、ラボ画面から本当にWebサイトにアクセスすることが可能です。 モニターを作成してみる それでは、早速Datadogを使ってモニターを作ってみます。モニターの種類は色々ありますが、ここではオーソドックスなメトリクスのモニターを作成します。 フォームを使ってゼロからモニターを作成する Monitor > New Monitor からメトリクスモニターを選択します。 1. 検出方法の選択 まずは、 どのように測定を行うか を決めます。モニターの種類によってその後の設定項目は変わってくるのですが、 ドキュメントページ ではタブ形式でその後何を設定すればよいか一目で分かるようにしてくれています。便利! 今回は、しきい値を選択し、メトリクスが一定の水準を上回った(下回った)場合にアラートを発報するようにします。 2. メトリクスの定義 ここでは、メトリクスを選択することで 何の値をモニタリングの対象とするか 、そしてそのグルーピングの仕方について設定を行います。今回は、monitors-labという環境タグがついた trace.flask.request.errors メトリクスの和をサービスタグごとにとっています(この環境では、 store-ads と store-discounts という2つのサービスが動いています)。 その下(評価の詳細)では、更に値の集計関数を規定しています。ここでは、上記グルーピングされたエラー数の過去5分の和を評価の対象としています。 3. アラート条件の定義 どのような場合にアラートを発報するか 、条件を指定します。しきい値の場合は、値がいくつより大きい/以上/以下/より小さい/等しい/等しくない場合にするかを指定します。 条件を入力すると、画面上部に表示されていたメトリクスのグラフと共にしきい値を表すラインが表示されました。 4. 通知の設定 通知設定では、変数を用いたカスタムの通知メッセージを作成できます。このメッセージは、メールの他にSlackなどを宛先とすることができます。今回は、ハンズオンの例と同じように変数を使わないシンプルなメッセージにしています。 5. 権限設定 モニターは、ユーザーの権限にかかわらず全員が見ることができます。またデフォルトでは、モニター編集権限を持っているユーザーが編集できるのですが、ここの項目では更にきめ細やかなアクセス制御をすることができます。 設定し終わったら、Createを押して作成完了です。 モニターのステータスを確認する Createを押すと、モニターのステータス画面に遷移します。作成したモニターの状態を確認してみましょう。 ヘッダー・プロパティ ヘッダーでは、モニターの状態( OK / 警告 / アラート など)が示されます。また、上部右側のボタンからは、アラートのミュートや解決ができます。なお、解決を押すとモニターは一時的に解決になりますが、再度メトリクスの値が評価された際にアラートの条件に当てはまっていれば再びアラート状態に移ります。プロパティでは、モニターの状態のほか、種類、作成時刻などのメタデータを確認可能です。 ステータスと履歴 ステータスと履歴のセクションでは、どのようにモニターの状態が移り変わってきたかを確認できます。 グループステータスのグラフでは、グループ化されたモニターのそれぞれについて状態が棒グラフで表示されます。今回は、 store-ads と store-discounts でグルーピングを行っているので、これらのグラフが表示されました。その下には、いつエラーが起こったのかを示す履歴グラフが表示されています。アラート時の挙動を見るためにしきい値を低く設定しているため、23:30頃のモニター作成とほぼ同時にアラート状態になっていることが分かります。 更にその下にあるのは評価グラフです。履歴グラフが生データ(未加工のデータ)を表示しているのに対し、評価グラフではこの生データに対して前述の手順「 メトリクスの定義 」の「評価の詳細」において定義済みの集計関数を適用した結果の値がアラート条件とともに視覚化されています。すなわち、今回の設定では過去5分間のエラー数の和がしきい値とともに示されています。 参考:新UI ステータス画面はまもなく新しいものに切り替わる予定です。 新しいUIでは、Visualize asの下の選択を切り替えることで生データのグラフ、評価値のグラフ、状態変化のグラフを表示することができます。   おわりに いかがでしたか?「Datadogのコースで学んでみたいけど、英語だからちょっとなぁ…」と思っている方にとって、この記事が足がかりとなれば幸いです。 ここまでお読みいただき、ありがとうございました。
膨大な構造化データ、半構造化データを抱え、その中から必要な情報を素早く分析したい。でも、システムに組み込むような本格的な分析ではなく、アドホックに分析したい。そんな時、一体何から始めたら良いのか途方に暮れた事はありませんか? 原因調査・仮説検証などスポット的なデータ分析を効率化したい データ量が多く処理時間・コストを短縮するためにデータを圧縮したい 可視化ツールを活用してレポートを作成したい 本記事では、 上記のような課題を解消するために、Amazon Athenaを用いて効率的にデータ化し、実行時間とスキャンデータ量を削減する方法と、Amazon Managed Grafanaを活用したデータ可視化方法をご紹介します。具体的な手順やサンプルを交えながら、Athenaでのクエリ作成からGrafanaでのダッシュボード構築までを解説します。データ可視化にお困りの方は、ぜひ読んでみてください。 アドホックなデータ分析をAWSで実現する3つのステップ アドホックデータ分析は、従来のデータウェアハウス構築・運用では時間やコストがかかりすぎるという課題があります。 Amazon AthenaではSQL文により、これらのデータを直接分析できるため、迅速なデータ分析が可能です。 Athenaに対応するファイル形式のデータをAWS S3に保存します。 データ変換やパーティショニングなどの前処理が必要な場合はAmazon Athenaを用いてSQLベースで実行し、分析に適した形式に整えます。 整形されたデータをAmazon Managed Grafanaに接続し、動的なダッシュボードと可視化ツールを用いて分析、洞察の抽出を行います。 S3は大容量データの保管に適したストレージであり、AthenaはS3に保管したファイルに対してSQLを用いたデータ操作が可能なため、データ準備に最適です。Grafanaは多様なデータソースに対応した可視化ツールで、Athenaで準備したデータを用いて効果的なデータ分析を実現できます。 どのようなデータ構造に対応しているの? 構造化データと半構造化データは、Athenaでのクエリが可能です。CSVやParquetなどの形式は構造化データとして、JSONやAvroは半構造化データとして扱われます。これらのデータ形式はAthenaで容易に分析が行えます。一方で、非構造化データは、Athenaで直接分析するのが難しく、別途構造化や前処理が必要です。 データ形式 概要 Amazon Athena対応 構造化データ スキーマを持つデータ 例:CSV、Parquet、ORCなど 〇 半構造化データ 部分的にスキーマを持つデータ 例:JSON、Avroなど 〇 非構造化テキストデータ 明確なスキーマを持たないデータ 例:Logstashログなど 〇 非構造化データ 明確なスキーマを持たないデータ 例:PDF、画像、動画 × どのようなファイル形式に対応しているの? Amazon Athenaで取り扱い可能なファイル形式は、構造化データ形式(CSV、TSV、カスタム区切り、 Apache Parquet、ORC )、半構造化データ形式(JSON、Apache Avro、Amazon Ion、CloudTrailログ)、ログファイル形式(Apache WebServerログ、Logstashログ)です。 ファイル形式 説明 Amazon Ion JSONと互換性のあるデータ形式 Apache Avro データシリアライズフレームワーク Apache Parquet 列指向ストレージ形式 Apache WebServer ログ パターンマッチングが可能なテキストデータ形式 CloudTrail ログ JSON形式 CSV カンマ区切り値 カスタム区切り ユーザー定義の区切り文字で分けられたテキストデータ形式 JSON 階層型データフォーマット Logstash ログ パターンマッチングが可能なテキストデータ形式 ORC 列指向ストレージ形式 TSV タブ文字で区切られたテキストデータ形式   データ用に SerDe を選択する - Amazon Athena 特定のデータ形式のテーブルを作成するために Athena で使用できる SerDe ライブラリを参照してください。 docs.aws.amazon.com データの可視化は簡単にできますか? Athenaのクエリ結果をAmazon Managed Grafanaのデータソースとして設定することで、簡単に連携が可能です。 Amazon Managed Grafanaは、複数のビルトインデータソースをサポートしており、さまざまなAWSサービスやその他のデータソースを可視化できます。Athenaのクエリ結果を動的なダッシュボードで表示し、多様な可視化オプションによりカスタマイズすることができます。   ビルトイン データソースに接続する - Amazon Managed Grafana すべての Amazon Managed Grafana ワークスペースで、次のデータソースがサポートされています。 docs.aws.amazon.com データ保管場所 分析対象のデータとクエリ実行結果は以下のようにS3バケット内の別々のフォルダに保存します。 データファイル保管場所: s3://<バケット>/athena/orgdata/sample.csv クエリなど実行結果の保管場所: s3://<バケット>/athena/query/   Amazon S3 でテーブルの場所を指定する - Amazon Athena Athena でテーブルを作成するときに、データの場所を指定する方法の詳細について説明します。 docs.aws.amazon.com   Athenaは指定されたLocation内のサブフォルダを再帰的にスキャンするので、スキャン対象以外のファイルは別のフォルダに保管します。 Athenaによるデータ分析の準備 Athenaを用いたアドホック データの取り込み、データ形式の変換、パーティショニング、アクセス用テーブルについて解説し、それぞれのテーブルの実行時間とスキャンデータ量を比較します。 データ取込みテーブル作成 本ステップでは、S3に保存されたデータ(今回はCSVファイルを使用)を読み込むための外部テーブルを作成します。データ構造をAthenaに伝え、データを読み込めるように準備します。  CREATE EXTERNAL TABLE IF NOT EXISTS csv ( 中略 ) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde' WITH SERDEPROPERTIES ( "separatorChar" = ",", "quoteChar" = "`", "escapeChar" = "\\" ) LOCATION 's3://<bucket>/athena/orgdata/' TBLPROPERTIES ('skip.header.line.count' = '1');   CSV を処理するための Open CSV SerDe - Amazon Athena Athena でカンマ区切りのデータ用のテーブルを作成する場合は、Open CSV SerDe ライブラリを使用します。 docs.aws.amazon.com   ROW FORMAT SERDE や SERDEPROPERTIES で適切なフォーマットを指定している点が重要です。 データ変換とパーティショニング 本ステップでは、各種変換処理を行い、新しいテーブルを作成します。例えば、Unixタイムスタンプは使いやすいデータに変換してカラムを追加します。テキスト形式からParquet形式への変換は、列指向フォーマットによる特定カラムへのアクセス高速化、効率的な圧縮によるスキャンデータ量の削減、そして各種データセットへの適合性から、クエリパフォーマンスが向上します。特に、SNAPPY圧縮は高速な圧縮と解凍により、クエリ実行速度向上に効果的です。また適切なパーティショニングにより、クエリ対象のデータが絞り込まれ、スキャンデータ量の削減によるパフォーマンス向上とコスト削減を実現します。 CREATE TABLE enhanced_csv_data WITH ( format = 'PARQUET', parquet_compression = 'SNAPPY', external_location='s3://<bucket>/athena/parquet/', partitioned_by = ARRAY['year', 'month', 'day'] ) AS SELECT *, CAST(date_format(from_unixtime(CAST(timestamp AS BIGINT) / 1000), '%Y%m%d%H%i%s') AS VARCHAR(14)) AS datetime_ymdhhmmss, year(from_unixtime(CAST(timestamp AS BIGINT) / 1000)) AS year, month(from_unixtime(CAST(timestamp AS BIGINT) / 1000)) AS month, day(from_unixtime(CAST(timestamp AS BIGINT) / 1000)) AS day FROM csv;   CREATE TABLE AS - Amazon Athena インライン SELECT クエリの結果を含むテーブルを作成します。 docs.aws.amazon.com 前ステップで作成した外部テーブルを圧縮しようとしたところ、以下のエラーが発生しました。パーティションキーのデータ型の指定がよくなかったようです。String型で再作成する事でエラーは解消されました。 アクセス用テーブル作成 前ステップで作成したパーティション付きデータへアクセスするための外部テーブルを作成します。テーブル名やカラム名などのメタデータ定義、LOCATION句によるデータ指定、パーティション情報の取得、tblpropertiesによるデータフォーマットと圧縮形式の指定といった役割を担います。 CREATE EXTERNAL TABLE IF NOT EXISTS parquet_csv_data ( 中略 ) STORED AS PARQUET LOCATION 's3://<bucket>/athena/parquet/' tblproperties ("parquet.compression"="SNAPPY");   Parquet SerDe - Amazon Athena Parquet SerDe を使用して、Parquet データから Athena テーブルを作成します。 docs.aws.amazon.com 各テーブルの実行時間とスキャンデータ量の比較 3つのテーブルに対して同一のクエリを実行して、実行時間とスキャンデータ量を比較すると以下となりました。 対象テーブル 実行時間 スキャンデータ量 CSVデータ取込みテーブル 6.29sec 127.96MB データ変換テーブル 6.71sec 12.69MB アクセス用テーブル 3.84sec 9.99MB CSVデータ取込みテーブルとアクセス用テーブルを比較すると、実行時間は38%削減されました。データ変換テーブルでCSV取込みテーブルよりも若干実行時間が増えているのはパーティションスキャンによるオーバーヘッドが考えられます。パーティションのスキャンデータ量を比較すると、列指向の特性と圧縮の効果により、スキャンデータが92%削減されました。圧縮により大幅にスキャンデータ量は削減されますが、それ以外にもテーブル構造やパーティションの違いによりクエリ実行結果に違いが出ることがわかりました。 複雑なテーブル構造はクエリ実行結果に影響を及ぼすので、パーティションの粒度や不要なカラムは除外するなど対処が必要です。   Grafanaによるデータ可視化 本章では、AthenaデータソースをGrafanaに設定し、Grafana Exploreでクエリを実行、ダッシュボードを作成する方法を紹介します。 アクセス制御 GrafanaからAthenaのデータ取得とS3へのログ書き込みについて、以下を参考にIAM 権限の付与を行います。 Amazon Managed Grafana の AWS マネージドポリシー - Amazon Managed Grafana Amazon Managed Grafana の AWS マネージドポリシーと、そのポリシーへの最近の変更について説明します。 docs.aws.amazon.com GrafanaにAthenaデータソース設定 データ転送を行うGrafana ワークスペースの[データソース]タブでAthena のデータソースを有効化し、アタッチ済みとなる事を確認します。               次にGrafanaのコンソールにログインし、データソースにAthenaが利用可能となっているか確認します。未利用の場合はinstall nowをクリックします。 Amazon Athenaに関するプラグイン説明画面が表示されるので、右上よりインストールします。 プラグインのインストールが完了するとAdd new data sourceと表示されるのでクリックします。 ここでは主にAthena Detailsの設定をします。 Grafana Exploreにてクエリ実行 Athenaとの接続が完了するとData Sourcesに新たに追加されるので、Exploreをクリックします。 Grafana Dashboardの作成 ここではGrafanaのデータソースとしてAthenaからの応答が正しい事をテストクエリを実行して確認します。特に問題なければ画面右上の+Addを展開してAdd to dashboardをクリックします。 次にOpen dashboard、Add visualizationをクリックするとダッシュボードのエディット画面が表示されるので、可視化を行いたいクエリを実行します。この時点では期待する結果とならない場合もありますので、Open visualization suggestionsからお好みの視覚化オプションを選択します。 視覚化オプションは多数あり、ダッシュボード上に異なるパネルを作成する事ができます。 さいごに Amazon S3、Amazon Athena、Amazon Managed Grafanaを使ったデータ分析ワークフローを3つのステップで解説しました。本記事が皆様のデータ活用にお役立ていただければ幸いです。
2024年12月からモバイルユーザのIP割り当て方法にアップデートが加わりました。 今回のアップデートでより柔軟な設定ができるようになりましたのでご紹介します。 おさらい ~モバイルユーザのIP割り当て方法~ Catoでは、CatoクラウドのPoPから各モバイルユーザに対してIPアドレスの割り当てを行います。 割り当て方法として、動的IP割り当てと固定IP割り当てがありますが、デフォルトは動的IP割り当てです。 モバイルユーザ用に用意されたアドレスレンジの中から動的にモバイルユーザにアドレスを割り当てを行います。 そのモバイルユーザ用に用意されたアドレスレンジはデフォルトで10.41.0.0/16に設定されています。   ここまではアップデート前も変わりません。 では、何が変わったのか?説明していきます。 アップデート概要 何ができるようになった? 最初にお伝えすると、今回アップデートが加わったのは動的IP割り当ての方法のみで、固定IP割り当ての方法に変更はありません。 変更点はズバリ、 複数のIPレンジから割り当てが可能 となる点です。 以前は1つのアドレスレンジ(Default IP Rangeと呼ぶ)からのみ割り当てを行っていましたが、別途アドレスレンジ(Dynamic IP Rangeと呼ぶ)を追加設定することで、複数のアドレスレンジから割り当てが可能になりました。 ユースケースとして、接続元IPアドレスレンジで社内システムへのアクセスを制御したい場合が考えられます。 例えば図のように、親会社のユーザはDefault IP Rangeから割り当てを行い、グループ会社のユーザには別途Dynamic IP Rangeを用意し割り当てを行うことで、グループ会社のユーザからのアクセスをIPアドレスレンジで制限するといったことができます。 もちろん、固定IPでも接続元IPアドレスレンジで社内システムへのアクセスを制御は可能です。 これまでこのようなユースケースの場合、固定IP割り当てを行っていました。 ただ、固定IPの場合設定したIPアドレスを利用できるのは最初に接続した端末のみです。 同一ユーザアカウントで2台目に接続した端末には動的にIPが割り当てられるため、制御は不十分だったと言えます。 Dynamic IP Rangeによる割り当ての場合は、同一 ユーザが2台同時接続をしたら2台とも Dynamic IP Range から割り当てが可能です。 そのため、このようなユースケースの場合は今回の追加機能であるDynamic IP Rangeによる割り当てがお勧めです。 Dynamic IP Rangeの設定方法や注意点はこの先で 詳しく説明していきます。 設定画面はどんな風に変わった? その前に、設定画面をみてみましょう。 以前は1つの画面にまとめられていましたが、2024年12月から設定画面が3つに分かれました。 Dynamic IP Allocation:動的IPの割り当てをするページ Static IP Allocation:固定IPの割り当てをするページ Settings:アドレスレンジを定義するページ ざっくりイメージは、まずSettingsでアドレスレンジの定義を行い、その後Dynamic IP AllocationやStatic IP Allocationで、ユーザやユーザグループに対して割り当てを行っていく流れになります。 また、Settingsのページを見てみると以下3つの項目があり、Default IP Rangeにはデフォルトで10.41.0.0/16が設定されています。 Default IP Range Dynamic IP Range Static IP Range Default IP Rangeの設定箇所をよく見ると「Define the default IP range for your remote users. This IP range is allocated to a remote user that does not match a policy.」という記載があります。 この記載から、Dynamic IP RangeやStatic IP Rangeのページで割り当てを行っていないユーザはDefault IP Rangeから割り当てとなることがわかります。もちろん、何も設定を行っていないデフォルト状態でも、このDefault IP RangeからIPが割り当てられます。 変更箇所がわかったところで、いくつかパターンを想定して実際にテストを行ってみました。 結果を次にまとめています。 設定方法 1つのアドレスレンジから動的に割り当てさせたい まず、1つのレンジから割り当てを行う場合です。 この場合は特に設定は不要です。上述の通りデフォルトの状態でDefault IP Rangeからのみ割り当てが行われます。 実際に接続をしてみると・・・ 10.41.138.26が付与されました。想定通りDefault IP Rangeから割り当てが行われていることがわかります。 ■UserAのIPアドレス ちなみに、10.41.0.0/16を既に利用しているなどの理由により、変更が必要な場合はSettingsページのDefault IP Rangeを任意のIPレンジに書き換えるだけで変更可能です。この点はアップデート前と同様です。 変更する際は、利用中のアドレスレンジと重複しないように注意しましょう。 複数のアドレスレンジから動的割り当てさせたい 複数IPレンジから割り当てを行いたい場合は、今回の追加機能を使います。 設定は以下の順番で行います。 設定手順: Dynamic IP Rangeの定義 Dynamic IP Allocation Policyの有効化 ポリシーを定義(ユーザ/ユーザグループへの割り当て) シナリオ: Dynamic IP Rangeを10.40.0.0/16と定義し、UserAにはDynamic IP Range(10.40.0.0/16)から、UserBにはDefault IP Range(10.41.0.0/16)から割り当てを行う。 設定 1.Dynamic IP Rangeの定義 SettingsページのDynamic IP Rangeに任意のIPレンジを定義します。 今回は、10.40.0.0/16にしました。 2.Dynamic IP Allocation Policyの有効化 Dynamic IP Allocation Policyはデフォルトでは無効化されているため、右上のトグルスイッチで有効化します。 有効化すると警告メッセージが表示されます。 このメッセージは「Dynamic IP Allocation Policyが有効になり、すべてのルールが実施されます。続行しますか?」という警告メッセージです。ルールが1つも定義されていない場合は、続行で問題ありません。(変わらずDefault IP Rangeからの割り当てになるため。)もし、既にルールが定義されている場合は問題ないことを確認してから、Continueで続行します。 3.ポリシーを定義(ユーザ/ユーザグループへの割り当て) アドレスレンジの定義ができたらDynamic IP Allocationのページ移動し、ポリシーを定義します。 私はここで、きっとUser/Groupsで対象のユーザを選択し、IP Rangeで作成したDynamic IP Rangeを選択するんだろうなと思っていましたが、IP Rangeでは、Network Rangeの作成が必要でした。 下図の「View network Range List」からNetwork Rangeの作成を行います。 今回は、10.40.0.1-10.40.0.100のNetwork Rangeを作成しました。 Network Rangeを2つ以上設定すれば、3つ以上のアドレスレンジから割り当てが可能ですが、今回は1つだけにしておきます。 Network Rangeの作成を行うと、Allocated Rangesの選択項目に出てくるので作成したNetwork Rangeを選択します。 当然ですが、このNetwork RangeはDynamic IP Rangeに含まれるレンジを選択する必要があります。 念のためDynamic IP Rangeに含まれないNetwork Rangeを選択してみたところ、以下のようなエラーが表示されて設定保存ができませんでした。 ▶error message:「The range XXX is not part of Dynamic defauld range」 正しいNetwork Rangeを選択しなおして今回は以下のようなポリシーを設定しました。 Name/Description:TestRule_1 User/Groups:UserA Platforms:Any Allocated Ranges:10.40.0.1-10.40.0.100 これで設定は完了です。 結果 この状態で、UserAとUserBを接続させると・・・ UserAには10.40.0.91が付与され、Dynamic IP Rangeから割り当てが行われていることがわかります。 ■UserAのIPアドレス 一方、UserBを接続してみると 10.41.113.182 が付与され、Default IP Rangeから割り当てが行われていることがわかります。 ■UserBのIPアドレス このように想定通り複数レンジからの割り当てができました。 補足 ここからは2つのシチュエーションを想定し、少し細かい仕様をQA形式でまとめています。 Q:Dynamic IP Rangeを使い果たしたら? →A:Default IP Rangeから割り当てを行います。  例えば、Network Rangeを10.40.0.1~10.40.0.100としGroupAに割り当てを行った場合、101番目に接続したGroupAに属するユーザにはDefault IP Rangeから割り当てが行われます。よって、ユーザアカウント数を考慮して Network Rangeを設定する必要があります。 Q:同一ユーザアカウントで2台同時接続したら? →A:2台ともDefault IP Rangeから割り当てを行います。 例えば、Network Rangeを10.40.0.1~10.40.0.100としUserAに割り当てを行った場合、UserAのアカウントで2台同時接続したら2台とも10.40.0.1~10.40.0.100から割り当てが行われます。よって、ユーザアカウント数に加えて接続 台数も考慮してNetwork Rangeを設定する必要があります。 Q:ポリシーが重複している場合は? →A:上位のポリシーが適用されます。  例えば、UserAがGroupAとGroupBの両方に属しており、下図のようにGroupAにはNetwork Range_1から、GroupBにはNetwork Range_2から割り当てを行うように設定を行った場合、UserAにはNetwork Range_1から割り当てが行われます。  Dynamic IP Allocation PolicyはCatoのFirewallなどのその他機能と同様で、上から順にチェックを行い一度ヒットしたらそれ以降は適用されない仕様です。必ず優先させたいポリシーを上位に設定するように注意しましょう。 まとめ 最後に、Dynamic IP Rangeを利用するうえでのポイントと注意点まとめると、こんなかんじです。 ・Dynamic IP Allocationページはデフォルトで無効化されている。   有効化したい場合はまず、SettingsページのDynamic IP Rangeを定義する必要がある。 ・Dynamic IP RangeはDefault IP Rangeと重複しないように注意が必要。 ・Network RangeはDynamic IP Rangeに含まれるレンジを定義する必要がある。 ・Network RangeはDynamic IP Range内で複数作成が可能。 ・ポリシーにマッチしないユーザには、Default IP Rangeからの割り当てとなる。 ・Network Rangeはユーザアカウント数と接続台数を考慮して設定する必要がある。 ・Dynamic IP Policyは上から順にチェックを行い一度ヒットしたらそれ以降は適用されないため、順番に注意が必要。 固定IPを割り当てたい 設定 固定IPの割り当てを行いたい場合はまず、SettingsページのStatic IP Rangeに任意のアドレスレンジを設定します。 今回は、192.168.2.0/24にしてみました。 アドレスレンジの定義ができたらStatic IP Allocationのページ移動します。 ここからは、アップデート前と全く同じです。 以下の流れで設定を行います。 有効化 デフォルトでは無効化されているため、トグルスイッチで有効化します。 アドレスの割り当て 対象のユーザをプルダウンで選択し、先ほど設定したアドレスレンジ(192.168.2.0/24)の中から1つアドレスを割り当てます。 今回の例の場合は、192.168.2.1を設定します。 その後、「Add」ボタンから追加を行います。 保存 設定内容を確認し保存を行います。 今回はUserAに対して192.168.2.1を割り当ててみました。 設定はこれで完了です。 結果 接続を行ってみると・・・ 想定通り192.168.2.1が付与されました。 ■UserAのIPアドレス 補足 ここからは2つのシチュエーションを想定し、少し細かい仕様をQA形式でまとめてみました。 Q:動的IPにて接続された状態で固定IPを割り当てたらどうなる? →A: 固定IPを使って自動的に再接続されます。この時断時間はほとんどありません。 この点はアップデート前から変更ありませんでした。 Q:固定IPを付与したユーザで、2台同時接続を行った場合どうなる? →A: 1台目の端末が固定IPを持ち続け2台目の端末には動的IPレンジから割り当てられます。 つまり固定IPが必要な端末数に合わせてユーザを作成する必要があります。この点もアップデート前から変更ありません。 まとめ 固定IPの設定をする際のポイントと注意点を改めて記載します。 Static IP RangeはDefault IP RangeやDynamic IP Rangeと重複しないように設定をする。 動的IPにて接続した状態で固定IPを割り当てた場合、固定IPを使って自動的に再接続され通信断時間はほとんどない。 2台同時接続した場合、固定IPが割り当てられるのは最初に接続を行った1台のみで、2台目にはDynamic IP RangeやDefault IP Rangeからの動的IP割り当てになる。 最後に 今回は、モバイルユーザのIP割り当て方法にアップデートが加わり、改めて記事にしてみました。 これからCato利用を検討されている方にも、既にご利用中の方にもお役に立てれば幸いです!
本記事は 新人ブログマラソン2024 の記事です 。 お久しぶりです。 USiZEサービス部の新人、織田です。 今回は「ITIL」についてまとめた記事です。ITILとは、簡単に言うと「IT運用の指針を提供してくれるフレームワーク」になります。 所属する部の名前にもある通り、私はUSiZEを運用する業務に携わっています。そのため、今後の業務にあたり必要となる考え方をITILを学習することで身に着けられるのではないかと考えました。今回の記事では、学習した内容を簡潔にまとめたいと思います。 それでは早速始めていきましょう! ※ USiZEとは、SCSKが提供するクラウドサービスです。詳しくは こちらのサイト をご覧ください。   ITIL とは何か? まず学習にあたり、気になったのが、「ITILとは何か?」です。 一言で大雑把にまとめると初めに述べた通り、「IT運用の指針を提供してくれるフレームワーク」であると思います。 ITILは1980年代後半に初めて登場した考え方であり、時代とともに変わるITシステムの提供形態の変化に合わせて、複数回のバージョンアップが行われています。 そのため、一言でITILについてまとめようとすると、どうしても大雑把な表現になってしまいます。 また、フレームワークという表現を使用しましたが、システム開発に使用されるプログラミング言語のフレームワークとは異なり、IT運用の考え方をまとめた枠組みのようなものになります。 そのため、ITILは多くのIT運用に考え方を適用できるように、抽象的とも感じられる部分が多々あります。 ITIL の歴史 ITILは1989年にイギリス政府の中央電算局(CCTA)によって初期バージョンが公開されました。その後、時代のニーズに合わせて複数回のバージョンアップが重ねられています。以下に主要なバージョンとそのリリース年、主な特徴をまとめました。 バージョン リリース年 主な特徴 ITIL  1989年 初期バージョン。30冊以上の書籍で構成され、大規模組織向けに設計されている。 ITIL v2 2001年 サービス提供と(Service Delivery)とサポート(Service Support)を明確化している。 ITIL v3 2007年 サービスライフサイクルの概念を導入し、IT運用全体をカバーしている。 ITIL 4 2019年 アジャイル、DevOps、リーンなど、現代的な手法を統合している。   ITIL 4 の特徴 最新バージョンであるITIL 4についてまとめます。 現代のIT運用手法との連携 ITIL v3までが主にウォータフォールモデルによる開発に対応していたのに対し、ITIL 4では、アジャイルやDevOps、リーンなどの最新の手法を統合しています。具体的な効果としては、より迅速なITサービスの提供や効率的な運用が可能となります。 サービスバリューシステム ITIL 4では、ITサービスの価値創出を「サービスバリューシステム(SVS)」として体系化しています。SVSの主要な構成要素は以下の通りです: ガバナンス :意思決定の枠組みを提供。 継続的改善 :価値を高めるための改善プロセス。 サービスバリューチェーン :価値を提供する一連のプロセス。 プラクティス :34のIT管理手法(例:インシデント管理、変更管理、問題管理など)。 従うべき原則 :組織で意思決定を行うためのガイダンス。 これにより、ITIL v3までのプロセス指向から価値指向へと進化し、柔軟性が向上したことで、変化の激しい現代社会により適したIT運用が可能となります。 ※ サービスバリューシステムは こちらのサイト に図として書かれています。   従うべき原則 「従うべき原則」には、さらに7つの項目があります。  価値に着目する  現状からはじめる  フィードバックをもとに反復して進化する  協働し、可視性を高める  包括的に考え、取り組む  シンプルにし、実践的にする  最適化し、自動化する 全部大切な考え方ですが、私が特に重要だと思った「現状からはじめる」について、ここでは特に詳しく説明させていただきます。 「現状からはじめる」は現状の評価と測定、観察を正しく行うことで、再利用可能なものを把握することを目的としています。 例えば、実務で古いシステムを移行しようとした場合、様々な制約事項があり、一から全部を新しく作り直したくなることがあります。 この時ほとんどの場合で、既存のものを活用することで移行に必要となる様々なコストを削減することができます。 ただ、反対に現状からまったく再利用できない場合もあることには注意が必要です。   ITIL 関連情報の収集方法 ここでは情報収集を2種類に分けて紹介します。 公式 ITILの歴史で書いたように、ITILはIT運用をまとめた書籍として提供されています。そのため、ITILの公式から提供される公式書籍(コア書籍)があります。このコア書籍の入手方法にはいくつか制限があるようなので、この場で簡単にまとめたいと思います。 コア書籍 デジタル版 印刷版 認定試験にバンドルされる。 ※必ずバンドルされているわけではないことに注意が必要。事前にバンドルされている試験であるか確認が必要。 ITILⓇ,PRINCE2Ⓡ公式書籍ショップ(IT&ストラテジーコンサルティング) から購入可能 研修 こちらのリンクに記載のある企業によって有料の研修が実施されています。 パートナー一覧 | PeopleCert – Best Practice by applying 私は新人研修でもお世話になったトレノケート株式会社が主催する「 ITIL(R) 4 Foundation BOOT CAMP 」に参加しました。 ※ITIL認定資格によっては、試験の事前要件として研修の受講が義務づけられているものもあります。   その他の学習方法 上記の公式から提供される書籍や研修以外にもITILには多数の書籍などがあります。 一般的な入手方法としては、 Amazonでの書籍の購入 Udemyでの資格試験対策講座や実務スキルの学習 などがあります。   ITIL 資格について ITILには、多数の認定資格があります。ここでは、最も基礎となるITIL 4 Foundationについて取り上げて概要をまとめます。 試験形式 :多肢選択式(オンライン受験可能) 試験時間 :60分(Foundation) 試験費用 :Foundationは約68,000~77,000円 日本語対応 :日本語試験が提供されています。 詳しい試験概要については、こちらのサイトをご覧ください。 ITIL®4 | PeopleCert – Best Practice by applying (ITILの認定資格の全体像をまとめたページ) ITIL®4 Foundation | PeopleCert – Best Practice by applying (ITIL 4 Foundationについてまとめたページ)   まとめ 以上で、今回の記事は終わりです。 私は「ITIL 4 Foundation」の合格を目指して勉強中です。 今回は学習したことのアウトプットもかねて記事を書いてみましたが、まだまだITILについての理解が浅いことを自覚できました。 これを機により一層勉強に励んでいきたいと思います。 もしかしたら、本記事を修正したリベンジ記事を書くかもしれません。
こんにちは、テクノロジーサービス部の大西です。 RSSフィードで取得した記事を要約し、自分のLINEアカウントに送信するシステムを構築しました。 今回対象にした技術ブログは本サイトであるTechHarmonyであり、SCSKでは様々な技術発信を高頻度で行っているため、特に自分の興味ある分野を見逃さないことを目的にしました。 作成したシステムについて Amazon Bedrockには様々なAIモデルが用意されています。モデルによってサポートされるリージョンや入力、出力形式が異なります。 (詳細は以下のページをご確認ください。) https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/models-supported.html 今回使用したモデルは、日本語対応の「Claude 3 Haiku」です。リソースは全てバージニア北部(us-east-1)に作成しています。 メインの処理を行うLambda関数はNode.jsで実装されており、RSSフィードのURLやLINEへのメッセージ送信用のアクセストークンはParameter StoreとSecrets Managerに保存しています。 また、重複した記事を取り込まないよう、DynamoDBで記事情報を管理しています。 メインの処理を行うLambdaはNode.jsを使用しており、RSSフィードのURLやLINEへのメッセージ送信で利用するアクセストークンは、 それぞれParameter StoreとSecrets Managerに保存しています。 また、重複した記事を取り込まないように、DynamoDBに記事情報を登録しています。 以下の例ではTechHarmonyの取得した記事をテーブルに書き込んでいます。 Lambdaを実行すると、以下のようにLINEに記事の要約が送信されました。 次の章から構築手順をざっくりとご説明していきたいと思います。 前準備 Node.jsで作成したソースコードは以下のモジュールを利用しており、事前にインストールが必要です。 ・axios ・RSSParser ・aws-sdk 私は自分のPCにワーク用フォルダを作成、その中にソースコードと追加モジュールを配置しており、 完成後はソースコードと追加モジュールをまとめたzipファイルを作成し、Lambdaへアップロードしました。 LINEへメッセージ送信は、LINE Messaging API( https://developers.line.biz/ja/services/messaging-api )を使用しています。 本サービスの利用にはLINEアカウントが必要です。 LINE Messaging API用意 LINEへ連携するため、LINE Messaging APIを準備します。 https://www.studycloudtech.com/aws/start-line-messagingapi/ 上記サイトを参考に構築し、以下のようにユーザーIDとチャネルアクセストーンを取得しました。 ※APIの使用料金は今回無料枠を選択しており、月200通までの送信が可能です。その他プランは以下を参照してください。 https://www.lycbiz.com/jp/service/line-official-account/plan/ DynamoDB用意 記事を保存するため、DynamoDBを作成します。パラメータは以下の通りです。 パラメータは以下の通りで、他の設定はデフォルト値を使用しています。 ①テーブル名:RSSArticles ②パーティションキー:ArticleID 文字列 Parameter Store作成 要約対象のページを追加・変更・削除する可能性を考え、RSSフィード取得先URLをParameter Storeに保存しています。 以下のようなパラメータで作成しました。 名前:/rss_sites/ 利用枠:標準 タイプ:文字列のリスト 値:任意のURL(画像はTechHarmonyのRSSフィードページ) 今回は1つのURLのみ指定していますが、今後複数のページから取得すること可能性を踏まえ、 タイプは「文字列のリスト」を選択し、拡張性を考慮しています。 Secrets Manager作成 LINE Messaging APIの手順で発行したチャネルアクセストークンを安全に保管するため、Secrets Managerを以下のように作成しています。 暗号化キーはSecrets Managerが発行するKMSキーを使用しています。 ①シークレットのタイプ:その他のシークレットのタイプ ②キー/値:LINE_ACCESS_TOKEN/<手順3で発行したチャネルアクセストークン> ③暗号化キー:aws/secretsmanager Bedrock使用アクセス申請 Bedrockで「Claude 3 Haiku」を使用するため、以下のような操作を行いました。 ①Bedrockを開き、「View Model catalog」を選択する。 ②今回使用するモデルである「Claude 3 Haiku」を選択する。 ③右上にある「・・・」を選択し、「Modify access」を選択する。 ④モデルアクセスのページに遷移するため、「特定のモデルを有効にする」を選択する。 ⑤リストから「Claude 3 Haiku」にチェックを入れ、「次へ」を選択する。 ⑥初回設定時にはユースケースを求められるため入力する。(私は自社情報を入力しました) ⑦入力した情報を確認し、「送信」する。 ⑧数分でアクセス権が付与される。ステータスを確認し、許可されたことを確認する。 IAM権限設定 Lambdaから呼び出されるリソースへの権限が必要になるため、IAMポリシーを以下のように設定し、 dynamoDB、Secrets Manager、Parameter Store、Bedrockへアクセスできるようにしています。 作成したポリシーは別途ロールへ付与します。 ・IAMポリシー ポリシー名:RSSPolicy {     "Version": "2012-10-17",     "Statement": [         {             "Effect": "Allow",             "Action": [                 "dynamodb:*"             ],             "Resource": "arn:aws:dynamodb:us-east-1:xxxxxxxxxxxxx:table/RSSArticles"         },         {             "Effect": "Allow",             "Action": [                 "secretsmanager:GetSecretValue"             ],             "Resource": "arn:aws:secretsmanager:us-east-1:xxxxxxxxxxxxx:secret:xxxxxxxxxx"          },          {             "Effect": "Allow",             "Action": [                 "ssm:GetParameter"             ],             "Resource": "arn:aws:ssm:us-east-1:xxxxxxxxxxxxx:parameter/rss_sites"          },          {             "Effect": "Allow",             "Action": "bedrock:*",             "Resource": "*"         }     ] } ・IAMロール ルール名:RSSRole 許可ポリシー:AWSLambdaBasicExecutionRole、RSSPolicy Lambda用コード作成 今回Lambdaで実行するコードは、Node.jsを使用して作成しています。 index.zip コードが長いので、上記ファイルをダウンロードして実ファイルと以下の説明を確認していただけるとわかりやすいと思います。 ①AWSサービスの初期化 まず、AWSの複数のサービスを利用するために、AWS SDKを使ってクライアントを初期化しています。 対象のサービスには、DynamoDB, Parameter Store, Secrets Manager, Amazon Bedrockがあります。 ②RSSサイトの取得 getRSSSites関数を使用して、Parameter StoreからRSSサイトの一覧を取得します。 取得された情報は、カンマ区切りの文字列として返され、RSSフィードを取得するために使用されます。 ③LINEアクセストークンの取得 getLineAccessToken関数では、Secrets ManagerからLINEのアクセストークンを取得します。 これは、LINE Messaging APIを使用して通知を送信する際に必要です。 ④新しい記事のフィルタリング filterNewArticles関数は、RSSフィードから取得した記事のうち、まだDynamoDBに保存されていないものをフィルタリングします。 既存の記事はDynamoDBから取得して比較します。 ⑤新しい記事の保存 新しく取得した記事は、saveArticles関数を使用してDynamoDBに保存します。 バッチ書き込みを使用して効率的にデータを保存し、万が一未処理のアイテムがあった場合には再試行を行います。 ⑥記事の要約生成 Amazon Bedrockのモデルを用いて、generateSummary関数が新しい記事の要約を生成します。 この要約はClaude 3 Haikuモデルによって提供され、レスポンスから要約を抽出します。 ここでは使用するモデルIDとバージョンの指定、AIへの命令方法がAPIとして提供されており、以下のページのAPIリクエストを参考にしています。 https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/model-catalog/serverless/anthropic.claude-3-5-haiku-20241022-v1:0 { "modelId": "anthropic.claude-3-5-haiku-20241022-v1:0", "contentType": "application/json", "accept": "application/json", "body": { "anthropic_version": "bedrock-2023-05-31", "max_tokens": 200, "top_k": 250, "stopSequences": [], "temperature": 1, "top_p": 0.999, "messages": [ { "role": "user", "content": [ { "type": "text", "text": "hello world" } ] } ] } } ⑦LINEにプッシュ通知 最後に、sendToLine関数を使って、新しい記事とその要約がLINEのユーザーにプッシュ通知されます。 LINE Messaging APIを利用し、事前に取得したアクセストークンを使用して安全にメッセージを送信します。 Lambda作成 作成したコードを実行するため、Lambdaを以下のように作成しました。 関数名:RSSNotifier(画像では既に作成済みで重複するため、_を付与しています) ランタイム:Node.js 22.x アーキテクチャ:x86_64 実行ロール:RSSRole 作成したコードとモジュールを含めたzipファイルを作成し、Lambdaにアップロードします。 アップロードした結果、以下のようにソースコードとモジュールが設定されていることを確認してください。 また、ある程度実行に時間がかかるため、設定画面からタイムアウト値を変更してください。 設定変更後、テスト実行すると、LINEに要約したメッセージが届きます。 まとめ Bedrockを用いたシステム構築に初挑戦してみました。 AIによる要約システムを作るのに多くの技術ブログやドキュメントに助けられました。 今後、EventBridgeを使用した定期実行やメッセージに参照元URLを含める改善を進めるのと、別AIモデルの動作についても検証していきたいと考えています。 閲覧いただき、ありがとうございました。
Amazon CloudWatch Logs を Amazon S3 にエクスポートする方法について、2つの構成を検討しました。 それぞれの構成にどのようなメリットや課題があったのか考察しておりますので、AWSでのログ収集の仕組みを考える際の参考になれば幸いです。 背景 コスト等の観点から、CloudWatch LogsのS3への保管を検討する方もいらっしゃると思います。 CloudWatch LogsをS3にエクスポートする手段は複数あり、今回は以下の要件に基づいて検討しました。   ・日次で定期的に処理を実施したい ・保存先S3のファイル名に日付を入れるなど、カスタマイズしたい   ①EventBridgeとLambdaによる日次エクスポート まず、EventBridgeを使ってLambda関数を日次で実行し、CloudWatch LogsをS3にエクスポートする方法についてです。   構成図     概要 EventBridgeで起動されたLambdaは、必要なタグ付けやエクスポート後のS3のディレクトリ作成を管理し、指定したログをエクスポートします。 シンプルな構成で、設計や構築が比較的容易のため、この方式の導入を検討される方も多いと思います。 課題 Lambdaで全てのロググループを一括で処理しようとしましたが、以下の制約にぶつかりました。 CreateExportTask APIの制限 同一アカウントでエクスポートタスクの並列実行ができないため、リソース制限エラーが発生。 Each account can only have one active (RUNNING or PENDING) export task at a time.   CreateExportTask - Amazon CloudWatch Logs Creates an export task so that you can efficiently export data from a log group to an Amazon S3 bucket. When you perform... docs.aws.amazon.com Lambdaの時間制限 実行時間が15分を超えるとタイムアウトする。 関数タイムアウト:900 秒 (15 分)   Lambda クォータ - AWS Lambda Lambda 関数および API リクエストに関する最大サイズ、制限、およびクォータです。 docs.aws.amazon.com   CreateExportTask APIの制限への対応として、sleep関数を用いて処理が終了するまで待機する構成をとるなどしました。しかし、エクスポート対象のロググループの数が多い場合にはLambdaの最大実行時間を超過してしまいました。   ②Step Functionsによる構成 次に、①の課題を解消するためにStep Functionsを導入した構成を紹介します。 構成図     概要 検証①からの主な変更点は、Step Functionsを使って各ロググループを個別に処理するLambdaを実行する構成にしたことです。 加えて、エラーハンドリング機能としてSNSを使用し、エラー時に即座に対応できるよう通知の仕組みを導入しました。 結果として、エクスポート対象のロググループの管理が容易となり、エクスポートの並列処理を避け、Lambdaのタイムアウトの問題も解消することができました。   <Step Functions構成イメージ> ※Lambdaをエクスポート対象のロググループの個数分設定する ※Describe-export-task APIにてエクスポート処理のステータスを確認する(処理がCOMPLETEになるまで待機する) ※Lambdaにてエラーが発生した場合、SNSでメール通知する     課題 Step Functionsでステップごとに処理ができるため、エクスポート対象のロググループの増減にも柔軟に対応可能となりました。しかし、エクスポート対象が多い場合、処理が複雑になり、構成に不備があった際に気づきにくくなるという新たな課題も感じました。   まとめ AWS環境でCloudWatch LogsをS3にエクスポートする方法について、2つの構成を検討しましたが、以下のような特徴があることを確認しました。   構成案 Lambdaによる構成 LambdaとStep Functionsによる構成 概要 EventBridgeを使ってLambda関数を日次で実行し、CloudWatch LogsをS3にエクスポートする。 EventBridgeとLambdaの間にStep Functionsを導入する。Step Functionsにて各ロググループを個別に処理するLambdaを実行し、CloudWatch LogsをS3にエクスポートする。 メリット シンプルな構成であるため、設計や構築が容易である。 エクスポート対象のロググループの増減にも柔軟に対応可能である。 課題 CreateExportTask APIの制限やLambdaの実行時間の制限を受ける可能性がある。 エクスポート対象が多い場合、処理が複雑になり、構成に不備があった際に気づきにくくなる可能性がある。   最後に CloudWatch LogsをS3にエクスポートするにあたり、APIの制約やLambdaの時間制限など、設計時に考慮すべき多くの条件があることを実感しました。   Step Functionsについて、②の検証を行うにあたり初めて使用しましたが、デザインエディタを用いることで直感的にフローを作成できることを知りました。 また、Step Functionsは、様々なサービスとの連携がサポートされています。 今回は①で利用したLambdaを活用する方向で②の構成を検討しましたが、Lambdaで記述したエクスポート処理と同様のことをStep Functionsのみで完結させる方式も考えられると思います。 よって、ログの転送処理だけではなく、複数のサービスを組み合わせたシステムを構築する際や、Lambdaのランタイムの制限などで実装が難しい際にはStep Functionsを活用していくメリットがありそうです。   CloudWatch LogsをS3にエクスポートする作業の必要性は今後も続くと考えており、今回の検討を選択肢の一つとして、多様なパターンを考慮しつつ、柔軟にシステム設計をしていきたいです。
今回はAzure上に構築済みのリソースを自動でコードに落とし込み、Terraform上で管理できるようにし、コードによってパラメータ変更ができるようにする方法について紹介したいと思います。 事前準備 Terraformの準備 前回私が投稿した以下サイトに習い、Terraformの準備をしてください。 TerraformでAzureにリソースを構築 IaCの中でもマルチクラウドに対応しているTerraformについて紹介したいと思います。 blog.usize-tech.com 2024.11.20 リソースの準備 事前にAzure上でリソースの作成をしてください。今回は以下のような設定のVirtual Machineを例にします。 コード作成 まず、既存リソースからコードを自動的に作成します。作成するにはimportブロックを用います。importブロックは任意の名前で作成した「.tfファイル」内に記述してください。 import { id = "/subscriptions/サブスクリプションID/resourceGroups/リソースグループ名/providers/Microsoft.Compute/virtualMachines/仮想マシン名" to = azurerm_virtual_machine.import-vm } idではVMのリソースIDを入力してください。リソースIDは対象VMの「プロパテイ」から参照することができます。 toの「import-vm」の部分はTerraform内での名前なので、自由に設定してください。 コマンド実行 以下コマンドにより、既存リソースの設定からコードを自動生成します。 terraform plan -generate-config-out = "ファイル名.tf" このコマンドを実行することで、コマンド内で指定したファイル名の「.tfファイル」が自動的に生成され、そのファイル内で以下のようなコードが自動的に生成されます。 resource "azurerm_virtual_machine" "import-vm" { location = "japaneast" name = "" network_interface_ids = [""] resource_group_name = "Terraform_Verification" tags = {Name = ""} vm_size = "Standard_B1ls" zones = ["1"] additional_capabilities { } boot_diagnostics { enabled = true # (1 unchanged attribute hidden) } os_profile_linux_config { disable_password_authentication = false } storage_image_reference { id = null offer = "ubuntu-24_04-lts" publisher = "canonical" sku = "server" version = "latest" } storage_os_disk { caching = "ReadWrite" create_option = "FromImage" disk_size_gb = 30 managed_disk_id = "" managed_disk_type = "StandardSSD_LRS" name = "" os_type = "Linux" write_accelerator_enabled = false # (2 unchanged attributes hidden) } delete_data_disks_on_termination = true } コードが生成出来たら以下コマンドを実行します。 terraform apply 上記コマンドを実行すると、「Plan:1 to import」と表示されるので、「yes」を記述し、Enterを押下します。 これによりリソースをTerraformで管理できるようになり、生成されたコードを修正し「terraform apply」を実行することでパラメータの変更ができるようになります。 注意事項 コードを自動生成する際に、ユーザ名やパスワードなどの機密情報等、パラメータによっては表示されないものがあります。生成されないパラメータの中には「terraform apply」実行時にエラーを発生させるものもありますので注意してください。どうしてもエラーを解消できない場合は、生成されたコードのresourceブロック内でエラーの出ているパラメータを以下のようにlifecycleブロックの「ignore_changes」で囲み、再度「terraform apply」を実行してみてください。 lifecycle { ignore_changes = [ os_profile, boot_diagnostics, additional_capabilities ] } このブロックは本来、値を変更したくないパラメータがあるときに使用するものですが、エラー解消に役立つので使ってみてください。 感想 たった数行のコードで既存のリソースを自動でコードに落とし込めるのは驚きましたし、コードを書くのが苦手な人でも一旦ポータル上で構築してから運用する際はコードで管理するということができるので非常に便利だと思いました。 おわりに 今回はTerraformによる既存Azureリソースのコード化について紹介しました。新規作成のみならず既存リソースの取り込みもできれば、運用も楽になると思いますのでぜひ使ってみてください。
こんにちは、Catoクラウド担当SEの中川です。 Catoクラウドより、2025年1月6日のアップデートにてAIアシスタントがリリースされました。 このAIアシスタントは、Catoの情報に特化した生成AIです! 主にCatoの仕様や設定方法などの確認、トラブルシュートなどに活用することが想定されます。 この記事では、AIアシスタントの実際の使用感や回答精度などについて記載しています! 機能概要 Understanding Cato’s Knowledge Base AI Assistant – Cato Learning Center 上記は、CatoがAIアシスタントについてまとめているページです。簡単にまとめると、以下のことが書かれています。 情報リソース : Knowledge Base の情報をもとに回答を提供しています。※特定のアカウントに関する具体的な回答は提供されません アクセス方法 : CMA右上のヘルプメニューからアクセス可能です 会話履歴の保存 : 同じセッション内であれば、会話は継続します。ただし、[クリア]を押したり、前の画面に戻ったりすると履歴は消えてしまいます。 情報の更新頻度 : AIアシスタントは週に一度ナレッジベースをスクレイピングして、最新の状態に保たれています。アップデートで機能改修などが入っても、数日のタイムラグで最新の情報に追いつきます。 対応言語 : 日本語でも問い合わせ可能ですが、ただし「最も正確な結果を得るには、英語で質問してください。」と記載されています。 また、実際に日本語で問い合わせると「 なお、今後のお問い合わせについては、英語でのご質問をお勧めいたします。 」というような文言を、AIアシスタント自体も時折回答の中に含めることがありました。 適宜、翻訳ツールを使って英語で質問するのが良いと思われます。 使ってみた結果 実際にAIアシスタントに、設定方法やトラブル中の問い合わせなどを聞いてみました。 動画形式で載せています。特にカットなどはせず、回答生成の時間はリアルな時間となっております。 CMAの設定方法について まずは、CMAでのTLSインスペクションの設定方法を尋ねてみました。 document.createElement('video'); https://blog.usize-tech.com/contents/uploads/2025/01/988504a1fcf69d56ec8cd15f81607ee1.mp4 TLSインスペクションの設定方法を教えてください かなり具体的にルールの設定値を教えてくれました。また、まだ公開されていない機能「TLS Inspection Configuration Wizard」の情報(1/24時点でEAのもの)も紹介してくれました。 特定のユーザのみに対象を絞る場合はどのように設定したらいいですか 想定していた回答は単純な「Sourceに指定します」程度の内容だったのですが、結果は違うものになりました。 最初にすべてをBypassするルールを作成し、テストユーザのみInspectするルールをその上位に設定するような方法を紹介してくれました。少数のユーザのみでテストする方法の Knowledge Base があることを私も把握できていなかったので、問い合わせしてみた価値がありました。 Bypassされたかイベントログで確認する方法はありますか https://blog.usize-tech.com/contents/uploads/2025/01/30764788b3503c13dab57e85082bd077.mp4 質問の意図としては、Home(旧UIではMonitoring)>Eventsでの確認方法を聞きたかったのですが、レポートでの出力方法が回答されました。 追加で、モニタリングのイベントログでの確認方法を聞き直したところ。想定通りの回答が返ってきました。 また、デフォルトでBypassされるOSや、証明書ピンニング問題についても触れてくれています。イベントログの確認方法だったので、トラブルシュートの一環の情報として紹介してくれたのでしょうか。丁寧な回答に思いました。 トラブルシューティングに関する質問 https://blog.usize-tech.com/contents/uploads/2025/01/4a41be417280d4b0248dcd49b91dcd05.mp4 特定のWebサイトへの通信がブロックされました。考えられる原因は何ですか 接続先側で制限がかかっている例と、CatoのInternet Firewallなどの設定が原因でブロックされている可能性の回答が得られました。 一次回答として網羅された内容かと思います。 パケットキャプチャの取得方法を教えてください https://blog.usize-tech.com/contents/uploads/2025/01/74cd8cbb2eab00c790bd020b6ee13b39.mp4 実際にトラブルシュートするときを想定して、試しにパケットキャプチャの取得方法を聞いてみました。Knowledge Baseに記載のあるものなので、これも自然に回答してくれました。 政府系サイトとは、例えばどのようなサイトが考えられますか 試しに技術的な内容とはやや外れる、一般的な質問として政府系サイトの例を聞いてみました。正直、抽象的な候補しかもらえませんでしたが、回答不可とはなりませんでした。 まとめ 良い点 全体的な回答精度としては高く感じました。簡単な言葉で端的に尋ねても、ほぼ想定した回答が返ってくる印象です。 また、Knowledge Baseのリンクを張ってくれることは便利だなと感じました。AIを利用する上では回答を100%信用するのは難しく、リンクがあればKnowledge Baseの内容によって判断することが可能だからです。 Knowledge Baseを利用したことのある方は共感いただけるかと思うのですが、Knowledge Baseはキーワード検索機能があまり優れていません。検索キーワードが含まれるおそらくすべてのページが引っかかってしまい、調べづらいのが正直なところでした。 この点、AIアシスタントが質問に応じて、適切なKnowledge Baseのページに誘導してくれることは大変ありがたいです。 気になった点 AIアシスタントの回答生成速度は動画をご覧いただいてもわかる通り、およそ30秒以内で回答してくれます。昨今利用される生成AIのスピード感と遜色ないかと思います。 ただし回答生成中に、ブラウザを切り替えたり、他のアプリなどに操作を移すと回答が止まってしまいます。回答が生成されるまで、ブラウザで待機している必要があります。 また、回答をもらった後、いざCMAの画面を操作しようとすると、AIアシスタントとのやり取りを閉じる必要がありました。その結果、会話履歴が消えてしまう点にかなり不便を感じました。 AIの回答を見ながらCMAの操作はできず、一度メモ帳などにペーストしてから操作する必要があることが現状感じる一番の難点です。 今後の所感 まだリリースされたばかりの機能のため、今後の機能改修や少なくとも回答精度の向上は期待できるのではないかと思います。 また、今回ご紹介したAIアシスタントとは別に、Internet FW上でAIを活用しベストプラクティスに準拠しているか確認する機能が直近追加されています。 こういったAIを活用した機能追加は、様々なところで見込めそうです。これからも期待が高まります!
近年、AIを活用した画像生成技術が飛躍的に進化しています。その中で、Re:Invent2024で発表されたAmazon Bedrockの新しい画像生成モデル「Amazon Nova Canvas」は新たな選択肢として注目を集めています。今回、Canvasを使って画像生成をしてみようと思います。   Amazon Nova Canvasとは? テキストや画像からプロ級の画像を作成する最先端の画像生成モデルです。プロンプト入力や直感的なインターフェースを通じて、ユーザーが簡単に高品質なビジュアルコンテンツを作成することができます。 特徴 1. 高精度な画像生成エンジン 最先端の生成AIアルゴリズムを採用しており、プロンプトに応じてリアルかつ魅力的な画像を生成します。その結果、ユーザーはわずかな入力でプロフェッショナルな成果物を得ることが可能です。 2. 柔軟なカスタマイズ 生成された画像に対して細かい調整が可能です。テキスト入力を使用して画像を簡単に編集できる機能、色調、スタイル、細部の編集など、多様な要望に応えられる柔軟性が魅力です。 3. 高速処理 画像生成のプロセスが迅速であることが特徴です。   Amazon Nova Canvasを使ってみる NOVA Canvasの利用可能な米国バージニア北部リージョンでBedrockサービスを開きます。   左メニューの[モデルアクセス]から「Nova Canvas」を選択します。   リクエストを送信すると、すぐに使えるようになります。   左メニューの[Image/Video]から、モデルに「Nova Canvas」を選択します。 推論では、「オンデマンド」と「推論プロファイル」を選択できます。「オンデマン」はサービスクォータまたはピーク使用時間によって制限される場合があります。「推論プロファイル」を選択すると、異なるAWSリージョンにまたがってリクエストをルーティングすることで、計画外のトラフィックバーストをシームレスに管理することができるようになります。 複数のAWSリージョンにトラフィックを分散することができるため、「オンデマンド」より高いスループットが可能になります。 今回は「オンデマンド」を選択します。 使えるようになりました!   画像生成を試してみる 画像を生成してみます。Actionで「画像を生成」を選択し、プロンプトにテキストを入力します。今回、英語でプロンプトを入力してますが、日本語入力も可能です。   「少年野球部員募集のチラシデザイン」をリクエストします。「画像サイズ」や「出力画像数」を指定することができます。 20秒程度で、1280×720サイズ、3種類の画像が生成されました。     気に入った画像があれば、そこからさらに別バリエーションで複数画像を作成できます。画像の右上からメニューを開き、「バリエーションを生成」を選択します。   下記の通り、3種類の画像が出力されました。   ユニフォームを青色に変更するよう指示すると、ユニフォームの色が変わりました。   もっと若い男の子に変更するよう指示すると、下記の通り出力されました。イラスト画像の出力パターンもありました。   画像を選択して、背景を削除したり、一部オブジェクトを指定して変更を加えることも可能です。   料金 今回、2時間ほどCanvasを利用し、料金は「$7.94」でした。   Canvasモデルのオンデマンドの料金は以下の通りです。 画像解像度 標準品質で生成された画像1枚あたりの価格 1024 x 1024 まで $0.04 2048 x 2048 まで $0.06 (2025年1月時点) まとめ 簡単な指示だけでリアルで高画質なデザイン画像を10秒~20秒程度で出力できました。広告、ウェブサイト、プレゼンテーションなどで使用するアートデザインの画像に活用できると思います。 プロンプトの日本語入力も試しましたが、画像がアジア人になったり漢字が含まれたりと、出力結果がアジアテイストになっている気がしました。 コストは画像1枚10円程度ですが、今回プロンプトからの指示をいろいろと変えながら、繰り返し同じような画像を生成したので、料金が少し高くなってしまったかもしれません。作成したい画像のイメージある場合は、イメージ画像をインプットに生成する方がコスト面の効率はいいかもしれません。   最後に、Canvasで自分の証明写真を元に、手書き似顔絵風のプロフィール画像を生成してみました。どれも似てないですが、一番近いと思われる左の画像をプロフィール画像として使ってみようと思います。    最後までお読みいただき、ありがとうございました。