AWSの最近の記事


  1. はじめに
  2. AWS Compute Optimizerとは?
  3. 対象リソースについて
  4. AWS Compute Optimizerの採用メリット
  5. AWS Compute Optimizerの採用デメリット
  6. 実装ステップ:AWS Compute Optimizerを有効化する方法
  7. AWS Compute Optimizerの導入で次の一歩を踏み出そう


1.はじめに

AWSのリソースコストを削減したいと考えていても、「会社のアカウント情報を第三者に見せるのはちょっと...」と不安に感じる方は多いと思われます。そこで安心して始められるコスト最適化の第一歩として、AWS Compute Optimizerをご紹介します。このツールは、専門知識がなくてもAWSのリソース利用状況を可視化し、最適化案を提案してくれる頼れる存在です。今回の記事では、このCompute Optimizerの仕組みや具体的なメリット、注意点を分かりやすくお伝えします。さらに、記事の最後ではコスト削減施策を次のステージに進めるための実践的なステップもご紹介しますので、ぜひ最後までご覧ください。


2.AWS Compute Optimizerとは?

AWS Compute Optimizerは、AWSリソースの設定と使用率メトリクスを分析し、最適なリソースサイズを提案するサービスです。このツールを使えば、現在使用中のリソースが過剰なスペックを持つ、または逆にスペック不足でパフォーマンスに影響を与えているかを簡単に判断できます。

主な特徴は以下の通りです。

視覚的なダッシュボードでリソースの使用状況を確認
最適化レコメンデーションを最大3件提供
対象リソースのコストやパフォーマンスの最適化を支援

AWS Compute Optimizerは無料プランと有料プランがあり、それぞれ異なるデータ分析期間をサポートします。

・無料プラン : 過去14日間のデータ分析

・有料プラン : 過去90日間の詳細データ分析(料金はリソース1時間あたり0.0003360215USD)


3.対象リソースについて

AWS Compute Optimizerでは、最適化の推奨事項を提供する対象が決まっています。対象となるのは、以下8個の主要リソースです。(2025年1月時点)

1. Amazon EC2 インスタンス

2. Amazon EC2 Auto Scaling グループ

3. Amazon EBS ボリューム

4. AWS Lambda 関数

5. Amazon ECS on Fargate サービス

6. 商用ソフトウェアライセンス

7. Amazon RDS インスタンス

8. Amazon RDS ストレージ

ただし、推奨事項を得るためには、2つ注意点があります。それについては、後の5. AWS Compute Optimizerの採用デメリットで詳しく触れたいと思います。


4.AWS Compute Optimizerの採用メリット

AWS Compute Optimizerを活用すると、単なるコスト削減にとどまらず、パフォーマンスの向上や運用の効率化といった幅広いメリットが得られます。「効率よくAWSリソースを使いたいけれど、何から始めればいいか分からない...」そんなお悩みを抱えている方にとって、最適なツールとなっています。それでは、Compute Optimizerを導入することで得られる主なメリットをご紹介します。


4-1.大幅なコスト削減

AWS Compute Optimizerは、リソースの使用状況を徹底的に分析し、過剰なスペックでコストがかさんでいる場合や、リソースを使いすぎている具体的な状況を教えてくれます。その結果、リソースの最適化を行うことで、AWSコストを最大25%削減することが可能です。例えば、普段気づきにくいオーバープロビジョンされたEC2インスタンスや、実はもっと低コストなストレージオプションで十分なEBSボリュームなど、目からウロコの気づきが得られるかもしれません。


4-2.パフォーマンスの最適化

「スペックが足りなくて処理が遅い」「逆にオーバースペックで無駄が多い」など、運用現場でよくある課題を正確に分析し、最適なスペックやサイズを提案してくれます。


4-3.迅速な導入

AWS Compute Optimizerの魅力の一つは、なんといってもすぐに使えるという手軽さです。AWS Management Consoleで有効化するだけで、レコメンデーションが自動生成され、すぐに最適化案を確認することができます。特別なセットアップやトレーニングも必要なく、まさに「今すぐ始められる」ツールです。AWSの利用経験が豊富な方はもちろん、初めて最適化に取り組む方でも直感的に使える設計になっています。


4-4.エンジニアの工数削減

これまでリソース最適化といえば、エンジニアが膨大な使用率データを分析し、最適なリソースサイズを手作業で見つけ出す必要がありました。Compute Optimizerは、こうした煩雑な作業を自動化します。エンジニアは最適化のためのデータ解析に時間を割く必要がなくなり、本来注力すべきプロジェクトや改善活動に集中することが可能です。結果的に、チーム全体の生産性を向上させることができるだけでなく、運用コストも削減できるという、一石二鳥のメリットを提供してくれます。


5.AWS Compute Optimizerの採用デメリット

どんなに便利なツールにも、効果的に活用するためには理解しておくべき制約があります。AWS Compute Optimizerも例外ではありません。このツールを導入する際に注意したい点を以下にまとめました。


5-1.対象サービスが限定的

AWS Compute Optimizerは、Amazon EC2やEBS、RDSなどの主要なリソースには対応していますが、すべてのAWSサービスを対象にしているわけではありません。たとえば、Amazon S3やDynamoDBなど、重要ながらも対象外となるリソースがあります。そのため、Compute Optimizerだけでは網羅的な最適化が難しい場合があり、場合によっては他のツール(AWS Trusted AdvisorやCost Explorer、Compute Savings Plans)との組み合わせや追加の手動作業が必要になります。


5-2.使用条件がある

Compute Optimizerのレコメンデーションを得るには、リソースが一定の条件を満たしている必要があります。例えば、最低でも過去14日間のメトリクスデータが収集されていることが前提となります。そのため、新しく作成したばかりのリソースや、使用頻度の低いリソースでは、具体的な提案が得られない場合があります。より詳細な分析を行う場合は、最大90日間のメトリクスデータを収集して実施する有料プランとなります。 こうした条件を理解しておくことで、Compute Optimizerの利用効果を最大化できるでしょう。


6.実装ステップ:AWS Compute Optimizerを有効化する方法

AWS Compute Optimizerは、手軽に有効化でき、導入後すぐにリソース最適化の提案を受け取ることが可能です。「具体的な手順が分からなくて不安...」という方のために、実際の画面を使った動画もご用意しましたので、ぜひそちらも参考にしてみてください。

以下では、Compute Optimizerを有効化し、実際にレコメンデーションを適用するまでのステップを簡単に解説します!



1.Compute Optimizerを有効化

AWS Management Consoleで「AWS Compute Optimizer」を検索し、有効化ボタンをクリック。

2.対象リソースを確認

自身の環境で分析対象となるリソース(EC2、EBSなど)を確認し、使用状況メトリクスが十分に収集されているかチェック。

3.ダッシュボードで結果を確認

推奨事項をダッシュボード上で確認し、最適化されたリソースに変更。

4.レコメンデーションの適用

提案された設定をもとに、リソースサイズや設定を調整。


7.AWS Compute Optimizerの導入で次の一歩を踏み出そう

AWS Compute Optimizerを利用することで、リソースのパフォーマンスを向上させながらコスト削減が実現できます。特に、自動化された分析と推奨事項は、運用コストを削減しつつ効率的なリソース利用をサポートしてくれる強力な味方です。

しかし、Compute Optimizerがカバーする範囲は限定的であり、一部のAWSリソースや環境における最適化はサポート外となる場合があります。

そのような網羅できない部分や、より高度な最適化の余地がある場合は、専門家のアドバイスを受けることが理想的です。アクセルユニバースでは、AWSアカウント全体を見渡して包括的なコスト削減を支援するAWSコスト削減チェックリストを提供しています。このチェックリストでは、Compute Optimizerでは対応できない領域もカバーし、さらに具体的で効果的な施策を実現できる内容が含まれています。

AWSのリソース利用をもっと最適化したい方や、現状のコスト削減施策を次の段階に進めたい方は、ぜひ以下のリンクをご覧ください。

AWSコスト削減を叶える18個のチェック項目

コスト最適化を効率的に進めたい方は、お気軽にアクセルユニバースにご相談ください!



X(旧Twitter)・Facebookで定期的に情報発信しています!


  1. 背景
  2. 原因調査
  3. 解決策
  4. 結果


1.背景

AWSを使用する多くの企業にとって、Amazon S3(Simple Storage Service)は最も利用されるストレージサービスの一つです。S3は、スケーラブルで信頼性が高く、データを安全に保存できるため非常に人気があります。しかし、使い方によってはストレージコストが膨らみ、毎月の予算を圧迫する原因にもなります。私たちAUCでは、SRE活動の一環としてAWSのコスト適正化を進めており、特にAmazon S3のコスト削減に焦点を当てました。

私たちがAmazon S3のコストを削減する上で直面した課題は、以下の点に集約されました。

  • データストレージが急激に増加し、不要なデータが放置されている。
  • データのライフサイクルポリシーが適切に設定されていないため、古いデータが自動削除されていない。
  • ストレージクラスを見直していないため、アクセス頻度の低いデータが高コストのストレージクラスに残っている。
  • データ転送の方法が最適化されていないため、予想外の転送料金が発生している。

これらの課題に対処するため、S3のコスト削減を図るための原因調査と最適化を実施しました。

この記事では、Amazon S3のコスト削減に向けた原因調査から解決策までのプロセスを具体的に記録します。


2.原因調査

まず、S3コストの内訳を確認するために、AWS Cost Explorerを活用してコスト分析を行いました。Amazon S3のコストは主に以下の2つの要素に分かれます。

  • データストレージ料金:保存されているデータ量に応じて発生するコスト。
  • データ転送料金:データをインターネットまたは他のAWSサービスへ転送する際に発生するコスト。

私たちの調査結果では、コストが急激に増加している主な原因は、ストレージクラスの選択ミスとデータライフサイクルの適切な管理が行われていなかったことにありました。また、転送コストが予想以上に高くなっていることも確認されました。以下、詳細な分析を進めました。


2-1.不要なデータの放置

長期間アクセスされていないデータが大量にS3バケットに保存されており、これがストレージコストを大幅に押し上げていました。具体的には、あるプロジェクトで使用されていたログデータやバックアップファイルが自動削除されることなく数年間にわたって保存され続けていたのです。


2-2.ストレージクラスの最適化不足

Amazon S3には、アクセス頻度に応じた複数のストレージクラスがあります。アクセス頻度が高いデータは「S3標準(Standard)」に保存されるべきですが、長期間アクセスされないアーカイブデータやバックアップデータに関しては「S3 Infrequent Access」や「S3 Glacier」などの低コストのクラスに移行すべきです。しかし、これが実施されていないために、全データがS3標準クラスに保存され、高いコストが発生していました。


2-3.データ転送の最適化不足

私たちの分析によると、EC2インスタンスからS3へのデータ転送が、VPCエンドポイントを使用せずに行われており、結果としてインターネット経由でデータが転送されていました。この設定ミスにより、不要なデータ転送料金が発生していました。


3.解決策

私たちは、以下のアプローチでS3のコスト削減を実現しました。


3-1.データライフサイクルポリシーの設定

まず、Amazon S3のデータライフサイクルポリシーを設定しました。これにより、特定期間が過ぎたデータを自動的にアーカイブする、あるいは削除することで、不要なデータが永続的に保存されないようにしました。例えば、アクセスされなくなってから90日を経過したデータは「S3 Glacier」に移動し、1年間アクセスがなかったデータは自動削除するように設定しました。

  • S3 Lifecycle Rules:特定のオブジェクトを指定期間後に低コストのストレージクラスに移行する、または削除するポリシーを適用。

これにより、アーカイブデータや古いバックアップデータが適切に管理され、ストレージコストを削減することができました。


3-2.ストレージクラスの見直し

次に、すべてのS3バケットに保存されているデータのアクセス頻度を分析し、ストレージクラスの見直しを行いました。アクセス頻度の低いデータは、「S3 Infrequent Access」または「S3 Glacier」に移行することで、ストレージ料金を大幅に削減しました。

  • S3 Standard:頻繁にアクセスされるデータ。
  • S3 Infrequent Access:アクセス頻度が低いが必要なデータ。
  • S3 Glacier:アーカイブデータ。

また、今後は新しいデータが自動的に適切なストレージクラスに保存されるように設定を行い、運用管理の負担を軽減しました。


3-3.VPCエンドポイントの導入

私たちは、EC2インスタンスとS3間のデータ転送を最適化するために、VPCエンドポイントを導入しました。VPCエンドポイントを利用することで、インターネットを介さずにVPC内部で直接データ転送を行うことができ、データ転送料金を大幅に削減することができました。

  • VPCエンドポイント(Gatewayタイプ):S3との通信をインターネットを介さずに行うことで、データ転送料金を削減。

VPCエンドポイントの利用により、データ転送料金を最大で80%削減することに成功しました。


3-4.S3インテリジェントティアリングの利用

さらに、S3インテリジェントティアリングという機能を活用しました。これにより、アクセスパターンに基づいて自動的にストレージクラスを最適化し、手動での移行作業を減らしました。インテリジェントティアリングは、データのアクセス頻度が減少した際に自動的に低コストのストレージクラスに移行してくれるため、長期間にわたってストレージコストの削減に寄与します。


4.結果

これらの最適化施策により下記の成果を得られました。


4-1.データライフサイクルポリシーの設定によるコスト削減

前提条件

  • 東京リージョン
  • 保存されているデータ量:10TB(10,240GB)
  • データのアクセス頻度は低く、90日後にほとんどアクセスされなくなる


アプローチ

  • 90日後に「S3 Standard」から「S3 Glacier」にデータを移行
  • 年間データを保持後、削除。


コスト計算

  • S3 Standard: 0.023USD/GB/月

→10,240GB × 0.023USD × 3か月 = 706.56USD

  • S3 Glacier Flexible Retrieval: 0.0045USD/GB/月

→10,240GB × 0.0045USD × 9か月 = 414.72USD

合計: 706.56USD + 414.72USD = 1,121.28USD/年


削減前のコスト

もし全データが「S3 Standard」に保存されていた場合 : 10,240GB × 0.023USD × 12か月 = 2,826.24USD/年


削減効果

1,121.28USD/年 vs 2,826.24USD/年 → 約1,705USDの削減(約60%の削減)


4-2.ストレージクラスの見直しによるコスト削減

前提条件

  • 東京リージョン
  • 10TBのデータのうち、頻繁にアクセスされるデータは40%(4TB)、残り60%(6TB)は低頻度


アプローチ

  • 頻繁にアクセスされるデータ(4TB)を「S3 Standard」に保持
  • 低頻度のデータ(6TB)を「S3 Infrequent Access」に移行


コスト計算

  • S3 Standard: 0.023USD/GB/月

→4,096GB × 0.023USD × 12か月 = 1,130.496USD/年

  • S3 Standard Infrequent Access: 0.0138USD/GB/月

→6,144GB × 0.0138USD × 12か月 = 1,017.4464USD/年

合計: 1,130.496USD + 1,017.4464USD = 2,147.9424USD/年


削減前のコスト

すべて「S3 Standard」に保存されていた場合 : 10,240GB × 0.023USD × 12か月 = 2,826.24USD/年


削減効果

2,147.9424USD/年 vs 2,826.24USD/年 → 約678USDの削減(約24%の削減)


4-3.VPCエンドポイントの導入によるデータ転送料金の削減

前提条件

  • 東京リージョン
  • 毎月、10TBのデータをEC2からS3に転送
  • 現在は、インターネット (NAT Gateway) 経由で転送しているため、データ転送料金、およびNAT Gateway配置料金が発生している


アプローチ

  • VPCエンドポイント(Gatewayタイプ)を導入し、インターネット (NAT Gateway) 経由の転送を排除


コスト計算

VPCエンドポイントデータ転送料金 : 0USD

VPCエンドポイント利用料金 : 0USD


削減前のコスト

  • NAT Gatewayデータ転送料金:0.062USD/GB/月

→ 10,240GB × 0.062USD × 12か月 = 7,618.56USD/年

  • NAT Gateway配置料金:0.062USD/時

→ 0.062USD × 8760h = 543.12USD/年

合計: 7,618.56USD + 543.12USD = 8161.68USD/年


削減効果

0USD/年 vs 8161.68USD/年 → 8,162USDの削減(100%の削減)


4-4.S3インテリジェントティアリングの利用によるコスト削減

前提条件

  • 東京リージョン
  • 保存データ:10TB(10,240GB)
  • オブジェクト : 1,000件
  • データアクセスパターン:最初の3か月は頻繁にアクセスされるが、それ以降はほとんどアクセスされない


アプローチ

  • 「S3 Standard」ではなく「S3 Intelligent Tiering」を使用
  • アクセスパターンに基づいて自動的に低コストのストレージクラスに移行


コスト計算

  • S3 Intelligent Tiering:最初の3か月は「S3 Standard」相当、以降は低頻度アクセスストレージに移行

  • 最初の3か月

Frequent Access Tier : 0.025USD/GB/月 → 10,240GB × 0.025USD × 3か月 = 768USD

  • 残りの9か月

Infrequent Access Tier : 0.0138USD/GB/月 → 10,240GB × 0.0138USD × 9か月 = 1,271.808USD

  • オブジェクト1,000件あたりのモニタリング・オートメーション料金 : 0.0025USD/月

0.0025USD × 12か月 = 0.03USD/年

合計: 768USD + 1,271.808USD + 0.03USD = 2,039.838USD/年


削減前のコスト

もし全データが「S3 Standard」に保存されていた場合 : 10,240GB × 0.023USD × 12か月 = 2,826.24USD/年


削減効果

2,039.838USD/年 vs 2,826.24USD/年 → 約786USDの削減(約28%の削減)


4-5.総合的なコスト削減効果

これらのアプローチを総合的に適用することで、S3のコストを大幅に削減することが可能です。

  • データライフサイクルポリシーによる削減: 約1,705USD/年
  • ストレージクラスの見直しによる削減: 約678USD/年
  • VPCエンドポイントの導入による削減: 約8,162USD/年
  • S3インテリジェントティアリングによる削減: 約786USD/年

これにより、合計で年間 約11,331USD の削減が見込めます。特に、データ転送コストの削減が大きなインパクトを与えていますが、データストレージの最適化も重要なポイントです。

今後の課題としては、さらなるデータの最適化と、各部門でのコスト意識の向上が挙げられます。AWSのベストプラクティスに従ったコスト管理を継続し、今後も新たなコスト削減の方法を模索していきます。



X(旧Twitter)・Facebookで定期的に情報発信しています!

目次


結局、何が違うのか?

こんにちは、アクセルユニバース株式会社、データサイエンティストの世古大樹です。

クラウド環境にデータウェアハウス(DWH)を構築しようとする場合、まず候補に上がるのはAWSの Redshift と、Google Cloud(旧GCP)の BigQuery でしょう。Redshiftが選ばれるのは、主に組織がすでにAWS上にシステムを構築しており、DWHも同じAWS上に作りたいからだと思います。AWSのシェアは国内トップであり(出典1)、「クラウドサービスならAWS」と考える企業も多いです。

一方、データ分析基盤に詳しい人は、Google Cloud のBigQueryを好みがちかもしれません。AWSがクラウドサービス全体をリードしているのに対し、Google Cloud はデータ分析や機械学習の領域に特別な強みがあると知られています。2019年に「DWHにBigQueryを採用しないことは大罪である」と主張するブログ記事(出典2)が公開され、このような意見は今も根強く残っています。

とはいえ、この記事の時からは月日が流れ、データウェアハウスを取り巻く環境は大きく変わりました。上のブログでRedshiftがBigQueryより劣っているとされた理由は「自前のクラスタ管理が必要など、フルマネージドでない」「スケールしない」という運用性の面でしたが、2022年に Redshift Serverless がリリースされ、BigQuery同様のフルマネージド・サーバーレスサービスとして使えるようになりました(今でもBigQueryの長所に「サーバーレス」を挙げる記事は多いですが、Redshiftもとっくにサーバーレスなのです)。

今は、単純に「RedshiftよりBigQueryの方が良い」と言えない状況です。両者の差は縮まっており、ほとんど同じ物のように見えます。RedshiftとBigQueryで共通している主な機能を、筆者が調査できた限りで表にしてみます。1つ1つ読む必要はありませんが、「これほど多くの機能が共通しているならどちらでもいいのでは?」と感じられるのではないでしょうか。

機能ジャンル 機能 備考
処理最適化 自動スケーリング
処理最適化 ストアドプロシージャ
処理最適化 クエリ結果のキャッシュ
処理最適化 マテリアライズドビュー
運用効率化 クエリのスケジューリング
運用効率化 ウェブベースのクエリエディタ Redshift:Redshift クエリエディタ v2
BigQuery:Google Cloud コンソール、BigQuery data canvas
運用効率化 クエリプランの取得 実行中のクエリを細分化したステージや進捗状況を表示する機能
SQLのEXPLAINステートメント
運用効率化 クエリの待ち行列(キュー) Redshift:WLM
BigQuery:クエリキュー
Redshiftはショートクエリを自動で判断して
待ち行列をスキップさせる機能もある。(後述)
運用効率化 手動のテーブル設計・
自動のテーブル最適化
拡張性 フェデレーテッドクエリ・
外部テーブル
DWH外部のストレージや関係データベースにクエリを
かける機能と、そのクエリに必要な便宜上のテーブル
拡張性 半構造化データへのクエリ Redshift:SUPERデータ型
BigQuery:JSONデータ型
拡張性 ユーザー定義関数(UDF) Lambda/Cloud Function を呼び出せるのも同じ。
拡張性 ほぼ全てのBIツールとの円滑な統合
拡張性 SQLでの機械学習モデル構築 Redshift:Redshift ML
BigQuery:BigQuery ML
セキュリティ 保存時暗号化 Redshift:KMSキーでの暗号化(オプション)
BigQuery:Google管理のAESキーでの暗号化(デフォルト)
レジリエンス デフォルトの地理的分散 Redshift:複数AZへの分散
BigQuery:複数ゾーンへの分散
レジリエンス 自動バックアップ Redshift:30分毎の復旧ポイントを0〜35日の設定期間にわたり保持
BigQuery:全時点のタイムトラベルを7日間保持
レジリエンス リージョンレベルの災害復旧 Redshift:スナップショット(手動バックアップ)と
復旧ポイント(自動バックアップ)のクロスリージョンレプリケーション
BigQuery:クロスリージョン・データセットレプリケーション
(プレビュー中の機能)

実際のところ、「どちらを使ってもあまり変わらない」というのも一つの見識だと思います。自社や担当者が詳しい方のクラウドを選択するのも手、です。

しかし、より詳しく見ていくと、両者には明確な違いもあることがわかります。このブログでは、それを 「運用性ならRedshift、コスパならBigQuery」 という視点に整理し、2回に分けて説明します。1回目の今回はRedshiftの運用性を解説します。読者の方が適切なクラウドサービスを選べる助けになれば幸いです。


Redshiftの運用性

Redshiftの運用性が高いと言える根拠は、「1. AWS上の対向システムとの統合容易性」「2. 機械学習ベースの管理タスク自動化」「3. Glue/Lake Formation による一元的なメタデータ・アクセス権限管理」の3つです。


1. AWS上の対向システムとの統合容易性

前述した通り、AWSは国内シェアが高く、クラウドサービス業界を牽引する存在です。そのため多くの組織のITシステムはすでにAWS上に構築されており、オンプレミスでホストされていても、AWSへの移行が検討される場合が多いです。DWHには、これらのITシステムからデータを受け取るための連携が必要なので、DWHも同じAWS上に立てると簡単になります。構成としては、データソース・データレイク・データウェアハウス・データマートをはっきり分けて構築する、以下のようなものが考えられます(あくまで一例です)。

スライド1.jpeg (筆者作成)

Glueが複数種類のデータソースを横断して、簡単にデータ収集・データレイク構築をしてくれるのが見て取れると思います。一方、AWSから Google Cloud へのデータ連携は複雑です。一般的なマルチクラウド構成の複雑さ(クラウド相互の認証認可、学習コスト、運用体制等)はもちろんのこと、RDSから Google Cloud へのデータ転送など、構築自体が大きく複雑になります。

AWS上のシステムと容易に統合できるRedshiftには、 運用簡素性・開発工数・自由度 の面でメリットがあるのです。


2. 機械学習ベースの管理タスク自動化

先ほどRedshiftとBigQueryで共通している機能の表を載せましたが、どちらかにしかない機能もあります。それらの機能の一つ一つは細々としたものですが、「機械学習ベースの管理タスク自動化」とまとめると、塵も積もれば山となる、Redshiftの強みと言って差し支えないものになります。

このことをより具体的に言うと、Redshiftは、 利用しているだけでデータやクエリの状況を自動的に判定し、DWHを最適化してくれる のです。他方のBigQueryは自動最適化の機能が限定的で、BIツールによるクエリを最適化する BI Engine がある程度です。基本的には、モニタリングを行って、その結果を判定し、手動でメンテナンスを行わなければなりません(出典3参照)。Redshiftであれば、機械学習などによって監視・判定・メンテナンスを自動化し、放っておくだけで処理を効率的にしてくれる様々な機能が提供されています。詳しく見ていきましょう。

バラしてしまうと、この節の元ネタは Black Belt(出典4) の、主に pp.20-33 です。この Black Belt 資料自体、Redshiftを理解するうえで必読のものなのでぜひ読んでいただきたいのですが、それはそれとして、この記事では Black Belt をもとにRedshift独自の(=BigQueryにはない)管理機能をまとめ、筆者の観点から補足を行います。


Redshift独自の自動管理機能のまとめ

  • カラム(列データ)の最適化
    • ゾーンマップとソートキー:カラムをあらかじめソートし、ディスクの物理ブロックごとに最小値と最大値を記憶しておくことで、不要なブロックを読み飛ばして処理する。
    • 圧縮エンコードの自動管理:カラムごとに最適なエンコード方式を自動で判定し、圧縮する。(手動選択も可能)
  • テーブルの最適化
    • 自動テーブル最適化:利用状況を判定し、ソートキーや分散キーを必要に応じて自動設定する。(手動設定も可能)
    • Vacuum Delete 自動化:Delete・Update 後の削除領域の開放を、適切なタイミングで自動実行する。(手動実行も可能)
    • ソート自動化:テーブル全体のソートは負荷が高くなるが、機械学習によってソートが必要な部分だけをピンポイントに、適切なタイミングでソートすることで、パフォーマンスやアクセスに影響なくソートできる。(手動ソートも可能)
  • ネットワークの最適化
    • データを均等分散して並列処理に最適化するだけでなく、JOINするレコード同士を同じ場所に置くことで、I/Oを削減できる。
  • クエリ実行の最適化
    • Analyze 自動化:テーブルの統計情報を適切なタイミングで自動更新することで、最適な実行計画のもとにクエリを行える。
    • Auto WLM:ワークロードごとに、物理リソース(メモリ・CPU等)の割当を自動で最適化する。
    • ショートクエリアクセラレーション:クエリの実行時間を予測し、短時間と判断されたクエリは、特別な領域でスムーズに処理される。(オフにもできる)


「ゾーンマップとソートキー」「自動テーブル最適化」について

たとえばテーブルの列 date: DATE がちゃんと日付順に並んでいないと、普通は WHERE date >= '2024-01-01' のようなWHERE句を含むクエリに対してフルスキャンを行う必要があり、応答時間や課金額が無駄に大きくなってしまいます。そこで列をいくつかの塊(1MBのブロックごと)にまとめ、塊の中の最大値と最小値をメモリに保存しておけば、最大値が 2024-01-01 未満である部分を読み飛ばして処理することができ、効率が上がります。これがゾーンマップです。

しかし、これだけではまだ無駄があります。読み込むブロックに含まれる全てのデータが 2024-01-01 以上とは限らないからです。例えば100件中1件のみが 2024-01-01 以上で、99件のスキャンは無駄だった、ということもありえます。そのため、さらに列のデータを降順にソートしておけば、少なくとも最大値が 2024-01-01 以上である最後のブロックの1つ前のブロックまでは全て 2024-01-01 以上ということになるので、効率的な処理が可能です。このようにソートする列を指定するものがソートキーで、適切なソートキーを自動設定してくれるのが自動テーブル最適化です。

スライド2.jpeg (筆者作成)

これらの機能は検索の効率を上げるという点で、インデックスに似ています。BigQueryにはインデックスがあり、一度作成したインデックスを自動管理してくれる機能もあります。しかし、最初にインデックスを作るには手動のDDLコマンドが必要であり、適切なインデックスを作るためにクエリパターンの監視・解析も必要です。管理の簡素さという点で、Redshiftに軍配が上がるところです。


3. Glue/Lake Formation による一元的なメタデータ・アクセス権限管理

これは厳密にはDWHの機能ではありませんが、AWSで多くの場合Redshiftと併用されるサービスのメリットとして挙げます。

「メタデータ」とは何かというと、データレイクやDWHに保存されているデータ(実データ)を説明する情報です。具体的には、テーブル・列・データ型・データソース・データ作成日などの説明です。そしてメタデータは「データカタログ」というデータベースに保管されます。データカタログを調べてメタデータを見れば、どのデータが「使える」データなのか、どの列が何を意味しているのかなどがわかります。DWHに蓄積される膨大なデータを活用するためには、「どこにどんなデータがあるのか」がわかることが重要です(わからないと使えるデータも埋もれてしまいます)。

データに対するアクセス権限管理についても、メタデータが重要な役割を果たします。たとえば、メタデータに「センシティブデータであるかどうか」という列を加え、それを利用してセンシティブデータを閲覧できるユーザーを制限する、というような運用が可能になります。また、(あまり無いことですが)機密情報に関わるメタデータ自体へのアクセスを制限することも考えられます。

AWSではETLとメタデータ・アクセス権限管理が一体化している ため、このあたりの管理が大きく省力化されます。先ほどの構成例をもう一度見てみましょう。

スライド1.jpeg

まず、下の Glue Crawler がデータソースを探索し、メタデータを作って Glue Data Catalog に保管します。保管されたメタデータの使い道は2つあります。1つはGlueのJob(ETLタスク)において、取得対象のデータを特定するために使われます。もう1つは Lake Formation で、テーブルの列単位などのきめ細かい粒度でのアクセス権限を設定するために使われます。Lake Formation のアクセス権限管理はデータレイクだけでなく、データマートにも及びます。Redshiftデータ共有と統合することで、コンシューマーRedshiftのアクセス権限を Lake Formation で管理することができるのです。

要するに、AWSではETLとメタデータがGlueという1つのサービスに合体しており、さらにGlueが統合的なアクセス権限管理を行う Lake Formation と高度に接続されていることで、データの管理負担が抑えられる、ということです。これは大きな特長です。

Google Cloud ではこうは行きません。ETLサービスであるDataflowにはメタデータ管理などの機能がなく、Data Catalog というサービスで別途データカタログを作成する必要があります。また、アクセス権限管理も Data Catalog、Cloud Storage(データレイク)、BigQuery(DWH)で個別に行わなければなりません(かなり大変そうじゃありませんか?)。特に Cloud Storage できめ細かいアクセス権限管理を行うことは、煩雑なため公式に非推奨とされています。Cloud Storage のきめ細かいアクセス権限管理はACL(Amazon S3 のACLと同様のものであり、現在はAWSでも Google Cloud でも非推奨とされている方式)で行う必要があるためです。


きめ細かいアクセスでは、2 つの異なるアクセス制御システム間で調整が必要になります。このため、意図しないデータ漏洩が発生する可能性が高くなり、リソースにアクセスできるユーザーの監査は複雑になります。特に、個人を特定できる情報などの機密データを含むオブジェクトが存在する場合は、均一なバケットレベルのアクセスを有効にしてバケットにデータを保存することをおすすめします。
(出典5)


......と言われても、一部のユーザーから隠さなければならない機密データを含むバケットで均一なアクセスを有効にするとなると、

  1. 機密データを見てはいけないユーザーがそのバケット(=データレイク)全体を見られなくなるか、
  2. 機密データを保管するバケットをデータレイクから分割し、そのバケットにアクセス制限をかけるか


しかありません。1だとそのユーザーのデータ利用が制約されてしまいますし、2だと「すべての生データを1箇所に集約する」というデータレイクのコンセプトそのものに反してしまいます。Google Cloud ではデータレイクのアクセス権限管理に課題があると言わざるを得ないでしょう。


まとめと次回予告

今回の記事では、BigQueryと比較したときのRedshiftの運用性について解説しました。ポイントをまとめておきます。


  1. RedshiftもBigQueryも、多くの機能が共通しているが、詳しく見ると「運用性ならRedshift、コスパならBigQuery」という違いがある。
  2. Redshift中心の構成では、AWS上の対向システムからデータ収集を行うのが簡単。
  3. Redshiftは、自動管理機能によって設定・監視・メンテナンスの負担が小さくなる。
  4. AWSでは、ETL・メタデータ・きめ細かいアクセス権限管理が Glue/Lake Formation に一元化されており、効率的な運用が可能。


次回は、実際にクエリを投げてかかった費用と応答時間を比較しながら、「BigQueryのコスパ」について解説します。「BigQueryはコストパフォーマンスに優れている」とはよく言われますが、必ずしもRedshiftより安くて速い訳ではありません。それでもBigQueryにあるコスパ上の利点とは何でしょうか?(次回記事はこちら


出典(いずれも記事公開時点閲覧)

  1. 総務省『情報通信白書令和6年度版 データ集』「第4章第8節 7. PaaS/IaaS利用者のAWS、Azure、GCP利用率」 https://www.soumu.go.jp/johotsusintokei/whitepaper/ja/r06/html/datashu.html#f00281
  2. データエンジニアの酩酊日記『近年のデータ分析基盤構築における失敗はBigQueryを採用しなかったことに全て起因している』 https://uma66.hateblo.jp/entry/2019/10/17/012049
  3. Google Cloud『BigQuery 管理の概要』 https://cloud.google.com/bigquery/docs/admin-intro?hl=ja
  4. Amazon Web Services『Amazon Redshift 運用管理 AWS Black Belt Online Seminar』 https://pages.awscloud.com/rs/112-TZM-766/images/AWS-Black-Belt2023Amazon-Redshift-Management0331v1.pdf
  5. Google Cloud『アクセス制御の概要』 https://cloud.google.com/storage/docs/access-control?hl=ja




X(旧Twitter)・Facebookで定期的に情報発信しています!

目次


「費用対効果」で選ぶには?

こんにちは。アクセルユニバース株式会社、データサイエンティストの世古大樹です。

今回は、以前のデータウェアハウス比較記事の続編で、BigQuery と Redshift Serverless のコストパフォーマンスを比較する実験を行いました。

詳しくは後述しますが、同じデータセットに対して同じクエリを実行し、かかった料金(コスト)と応答時間(パフォーマンス)を計測しています。

データセットは、80GiB程度の構造化データと360GiB程度の半構造化データの2種類を利用します。それぞれのデータセットに対し、性質の異なる3つのクエリ(合計6つのクエリ)を書きました。クエリ1つにつき5回実行して、特有のオーバーヘッドがある1回目を除外し、2〜5回目の計測結果の平均値を取っています。

「BigQueryの方が安価で性能が良い」とよく言われているようですが、実際に比較した結果を公開しているものは見当たりません。本記事を読めば、コストとパフォーマンスに根拠を持ってデータウェアハウスの選定ができるようになります。


結果:BigQueryは「安定」している

実験の詳細は後回しにして、いきなり結果から発表したいと思います。詳細は .xlsx ファイル(こちらからダウンロード)でご確認いただけますが、ここでは概要の解説を行います。

まず、「コスト」にあたる平均課金額は以下のようになりました。(データセットやクエリの内容は後述します)

スクリーンショット 2024-10-01 15.49.13のコピー3.png

「差」「比」はともに「BigQuery 容量コンピューティング」と「Redshift Serverless」を比較したもので、BigQueryが有利な場合は青色、Redshiftが有利な場合は赤色で表現しています(以降の表も同様)。

「比」を見ると、思いのほか傾向が一定していないのが驚きです。BigQueryの方が安いクエリも、Redshiftの方が安いクエリもあります。クエリ1-1はBigQueryの方が約13倍高い一方、2-2はRedshiftの方が15倍高くなり、ばらつきが大きいようです。

次に、「パフォーマンス」にあたる平均応答時間は以下のようになりました。

スクリーンショット 2024-10-01 15.49.13のコピー2.png

BigQueryの応答時間は比較的安定している(425〜27,212ms、約64倍)のに対し、Redshiftはかなり開きがある(68〜158,411ms、約2300倍)のが目を惹きます。RedshiftのRPU(仮想的な演算リソース)は、BigQueryと近い応答時間になるように設定したのですが、実際に比を1付近にできたのは1-2と2-3だけです。1-1と2-2ではRPUを最低にしてもBigQueryより大幅に速くなり、逆に1-3と2-1ではRPUを非常に大きくしてもあまり速度が上がらず、BigQueryには遠く及びませんでした。

「BigQueryの方がパフォーマンスが高い」とよく言われていますが、むしろ正確には、「BigQueryの方がパフォーマンスが安定している(Redshift Serverless ほど極端に長い応答時間を必要としない)」傾向にありそうだ、ということが読み取れます。

また、平均課金額の表で垣間見えていた、各DWHにとって「どのクエリが得意/不得意か」の傾向は、応答時間にも共通しており、課金額の比が大きい順に平均応答時間の比も大きくなりました。つまり、どちらのDWHにも、「得意なクエリは安いし速い」「苦手なクエリは高いし遅い」という相対的な傾向があるようです。

そこで、各クエリがそれぞれのDWHにとってどの程度「得意」かを表す指標を作ります。平均応答時間の逆数を、クエリに対するDWHの「パフォーマンス」、平均課金額を「コスト」と捉え、パフォーマンスをコストで割ります。この「コストパフォーマンス指数」が高いほど、そのDWHがそのクエリを「得意」としていることを示します。

スクリーンショット 2024-10-01 15.49.13のコピー.png

まず行ごとに「比」を見ると、BigQueryがRedshiftの何倍のコストパフォーマンスを示したかがわかります。全体的にはBigQueryが上回っており、特に2-1では210倍もの差になっていますが、6個中2つのクエリではRedshiftが優勢で、1-1では83倍の差です。必ずBigQueryの方が優れているとは言い切れず、「どちらが良いかは場合による」ことになります。

実験した限りでは、Redshiftが上回った場合の共通点は、「RPUが最低の8でも非常に速いこと(数秒以内)」でした。「CTE(サブクエリ)があるとRedshiftが不利になる傾向にある」ということも言えそうですが、サブクエリはメモリサイズをボトルネックとする処理なので、「メモリサイズと比例するRPUの数を増やしても、サブクエリを含むクエリがあまり速くならないこと」の説明がつきません。事前には、BigQueryではインデックスを張れるのに対しRedshiftではソートキーの指定しか行えないため、JOINが含まれるとBigQueryが大幅に速くなると予想していたのですが、そういった傾向もありませんでした。

困ったことに、BigQueryの測定から得られる情報(スロット数・応答時間・処理データ容量)からは、Redshiftの方が良いのかどうか予想できません。言えるのは、「Redshift Serverless を使っている場合、RPU数が小さくなければBigQueryに移行した方が良くなる見込みが大きい」ということです。

次に列ごとに(縦に)表を見ると、こちらははっきりした傾向が読み取れます。値が大きいほどそのDWHにとって簡単な処理で、逆に小さいほど難しい処理だということになり、最大値と最小値の幅が狭いほど、常に安定したコストパフォーマンスを発揮できることになります。BigQueryの方が、平均課金額・平均応答時間ともに幅の開きが小さかったため、コストパフォーマンス指数も安定しました。BigQueryは 0.00012〜2.4 の20,000倍、Redshiftは 0.0000023〜200 の約90,000,000倍です。「BigQueryのコストパフォーマンスは、Redshift Serverless に比べて、(優れているというより)安定している」というのが、この実験における最も重要な結論です。

平均前の測定値、RPU数、課金額の計算方法などの詳細、および注意事項などは、 .xlsx ファイル(こちらからダウンロード)をご覧ください。


実験条件

以下では、どのような条件の下に実験を行ったのかを、「データセット」「データウェアハウス設定・計測条件」「クエリ」に分けて述べます。ただし、実際に利用したクエリ文等は非常に長いので、末尾の「コード集」にまとめて掲載しました。ここでは日本語ベースで、概要や意図だけを説明します。


データセット

利用したデータセットの1つ目は、Chicago Data Portal の Taxi Trips (2013-2023) です。シカゴ市が公開している、市内のタクシーの賃走についてのデータセットです。11年分の運行について、タクシーID、開始・終了時刻、走行距離、運賃などが記録されています。CSV形式で23列×約2億行、解凍時サイズは約80GiBの、単一テーブルのデータです。表では「小規模構造化データ」と呼んでいます。

2つ目は、Hugging Face にある McAuley-Lab の Amazon-Reviews-2023 です。1996年から2023年までに amazon.com へ投稿された商品レビューが収集されています。レビューデータの集まりである User Reviews、レビューされる商品の情報である Item Metadata の2種類のデータがあり、さらにそれぞれ商品カテゴリでデータセットを分割されています。実験では、商品カテゴリによって分割されたデータを1つにまとめ、種類に応じて2つのテーブルとしました。いずれもJSON形式で、User Reviews は約260GiB、Item Metadata は約90GiB、計360GiBほどです。表では「中規模半構造化データ」と呼んでいます。

いずれも GCS/S3 バケットに保存し、そこから BigQuery/Redshift へロードしました。


データウェアハウス設定・計測条件

今回の実験では、「実際にDWHの利用を開始した時のパフォーマンスを再現すること」を目指し、現実の利用開始時に近い設定としました。

パフォーマンス最適化の基本としては、BigQueryではインデックスの作成、Redshiftではソートキーの指定ができます。DWHの利用が進んでいけば、メトリクスに基づいて最適なインデックスを構築したり、ソートキーが自動的に最適化されたりするところですが、普通、利用開始時にはそこまで行わないと思います。とはいえ、最適化を何も行わないのもリアリティがありません。そこで今回は、「インデックスは主キーにのみ張り、ソートキーにはタイムスタンプ列を指定する」というシンプルな設定にしました。また、RedshiftのVACUUMは、各データベースでデータロード完了後の1度のみ実施しました。

計測に際しては、信頼度の高いデータとするため、リザルトキャッシュの取得を無効化した上で5回連続で同じクエリを行い、2〜5回目の計測結果の平均値を取りました。1回目の結果を除くのは、Redshiftで初回のみコードコンパイルが行われるなど、例外的なオーバーヘッドが発生しうるからです。

リージョン(ロケーション)については、AWS・Google Cloud ともに全て東京単一リージョンで実行し、料金も東京の金額で計算しました。

BigQueryの課金モデルは、予約したスロット(仮想的な演算リソース)の利用量に基づく「容量コンピューティング」と、スキャンしたデータ量に基づく「オンデマンド」の2種類があり、さらに「容量コンピューティング」には3つのエディションがあります。BigQueryの利用を開始する場合、まず「オンデマンド」で自社の利用量等を把握し、「容量コンピューティング」の予約に移行することが想定されていますが、初めから「容量コンピューティング」を使うことも十分あり得ます。そこで今回は、「オンデマンド」を利用してその課金額と処理データ量を記載しつつ、「容量コンピューティング・Standardエディション」の場合のスロット数と課金額も計算し、記録しました(こちらの数値を元に、他のエディションの金額も計算可能です)。

Redshift Serverless の課金額は、RPU(仮想的な演算リソース)の利用量に基づきます。このRPUのベース値は8〜512の間で指定することができ、大きくすると応答時間は短くなりますが、ある程度を超えると短縮効果がコストの増加に見合わなくなります。今回は、原則的にBigQueryの応答時間と近くなるように設定しつつも、コストに見合わないほど大きな値にはしないようにしました。例えばクエリ1-3の応答時間は、RPUが128のとき約160秒でしたが、最大の512に設定しても約100秒と、40%の時短に対して2.5倍のコストになります(コストパフォーマンス指数は0.64倍)。BigQueryは約20秒でしたが、それにできるだけ近づけるのではなく、現実的なラインと考えられた128RPUに設定しました。

なお、最適なRPU数を探索するためのクエリは、測定に影響を及ぼさないように、別のデータベースで行いました。また、Redshift Serverless には1分間の最低課金時間があり、1分未満のクエリであっても1分間分の料金が発生します。しかし実際の利用においては、1分未満のクエリも、他のクエリと同時に実行することで合計1分以上にできると考えられるため、測定されたままのミリ秒数に基づいて料金を計算しました。

以上の料金は、演算(クエリ)に対する費用であり、実際にはストレージ(データ保存)に対する費用も発生しますが、そちらは(通常の利用では)演算に対する費用に比べてかなり安価になることと、デモを行わなくても簡単に見積が取れることから、計測を行いませんでした。また、本記事に掲載されている料金についての情報は公開時点のものであることにご注意ください。料金の詳細について、BigQueryはこちら、Redshiftはこちらをご覧ください。

計測結果の取得には、BigQueryでは後に掲載するクエリを用いました。Redshiftでは、クエリエディタv2のリザルトに表示される Elapsed time で応答時間を計測し、応答時間にRPU数とRPU時間あたりの料金を乗じて課金額を計算しました。RPU数が指定したベースRPU数の通りであることはコンソール上で確認しました。


クエリ

DWHパフォーマンスのボトルネックとして代表的な処理は、ディスクI/OとCPUに負荷のかかるソート(結合・ORDER BY句・ウィンドウ関数)と、メインメモリを消費するサブクエリです。そのため、DWHの主なワークロードである集計(集約関数)を全クエリに含めながら、これらの句や関数の様々な組み合わせを試しました。

できるだけ標準SQLに準拠するようにしました。方言の違いにより、BigQueryとRedshiftで全く同じクエリ文にはなりませんでしたが、同じ処理を実現するものになっています。

また、クエリは集計・分析として意味を持つように作成し、コード集にはその説明も付けておきました。


コード集

前処理

Amazon-Reviews-2023 の Item Metadata は、そのままだと BigQuery の仕様でエラーが出るので、以下のPythonスクリプトで前処理しました。Redshiftの場合は前処理なしで読み込めますが、同一条件で比較するために、同じく前処理したデータをロードしています。



import json
import re

def clean_columns(obj):
    if isinstance(obj, dict):
        keys = list(obj.keys())
        for key in keys:

            # テーブル定義に合わないデータ型を修正する。
            if key == 'rating_number' and not isinstance(obj[key], int):
                del obj[key]
            elif key in ('average_rating', 'price') and not isinstance(obj[key], float):
                del obj[key]
            elif key == 'details' and not isinstance(obj[key], dict):
                del obj[key]
            elif key in ('videos', 'images', 'features', 'description', 'categories', 'bought_together') and not isinstance(obj[key], list):
                obj[key] = []
            elif key == 'images':
                images = obj[key]
                for image in images:
                    for image_size in list(image):
                        if not image_size in ('thumb', 'large', 'variant', 'hi_res'):
                            del image[image_size]
                            print(str(image_size) + 'を削除しました。')

            # BigQueryの仕様に合わせたキーの前処理:使用できない特殊文字を消去し、大文字・小文字の違いを無視する。衝突が発生するか空文字列になる場合は削除する。
            cleaned_key = re.sub(r'[!"$()*,./;?@[\]^`{}~]', '', key.lower())
            if key != cleaned_key or cleaned_key == '':
                if cleaned_key in obj or cleaned_key == '':
                    del obj[key]
                else:
                    obj[cleaned_key] = obj.pop(key)

        for value in obj.values():  # ネストされたオブジェクトに対して再帰的に処理を行う。
            clean_columns(value)
    return obj

def main():
    with open('item_metadata_before_cleaned.jsonl', 'r') as input, open('item_metadata.jsonl', 'w') as output:
        for line in input:
            obj = json.loads(line)
            obj = clean_columns(obj)
            cleaned_line = json.dumps(obj)
            output.write(cleaned_line + '\n')

if __name__ == '__main__':
    main()


データロード等

Taxi Trips (2013-2023), BigQuery

このデータセットのタイムスタンプ形式はBigQueryにサポートされていないので、一度文字列型で読み込んでから変換しています。 また、各データセット共通ですが、BigQueryでは4GB以上のファイルを圧縮形式でロードできないので、解凍したデータを読み込んでいます(Redshiftでは圧縮したまま利用しています)。



CREATE SCHEMA taxi_dataset 
  OPTIONS(
      location='asia-northeast1',
      storage_billing_model='LOGICAL'
  );

CREATE TABLE taxi_dataset.TaxiTrip (
    trip_id STRING,
    taxi_id STRING,
    trip_start_timestamp STRING,
    trip_end_timestamp STRING,
    trip_seconds INT,
    trip_miles FLOAT64,
    pickup_census_tract STRING,
    dropoff_census_tract STRING,
    pickup_community_area INT,
    dropoff_community_area INT,
    fare FLOAT64,
    tips FLOAT64,
    tolls FLOAT64,
    extras FLOAT64,
    trip_total FLOAT64,
    payment_type STRING,
    company STRING,
    pickup_centroid_latitude FLOAT64,
    pickup_centroid_longitude FLOAT64,
    pickup_centroid_location GEOGRAPHY,
    dropoff_centroid_latitude FLOAT64,
    dropoff_centroid_longitude FLOAT64,
    dropoff_centroid_location GEOGRAPHY,
    PRIMARY KEY(trip_id) NOT ENFORCED
);

LOAD DATA INTO taxi_dataset.TaxiTrip
FROM FILES (
    allow_jagged_rows=true,
    field_delimiter=',',
    format='CSV',
    null_marker='',
    skip_leading_rows=1,
    uris=['gs://my-bucket-name/TaxiTrip.csv']
);

ALTER TABLE taxi_dataset.TaxiTrip
    ADD COLUMN new_trip_start_timestamp TIMESTAMP,
    ADD COLUMN new_trip_end_timestamp TIMESTAMP;

UPDATE taxi_dataset.TaxiTrip
    SET
        new_trip_start_timestamp = PARSE_TIMESTAMP('%m/%d/%Y %I:%M:%S %p', trip_start_timestamp),
        new_trip_end_timestamp = PARSE_TIMESTAMP('%m/%d/%Y %I:%M:%S %p', trip_end_timestamp)
    WHERE true;

ALTER TABLE taxi_dataset.TaxiTrip
    DROP COLUMN trip_start_timestamp,
    DROP COLUMN trip_end_timestamp;

ALTER TABLE taxi_dataset.TaxiTrip
    RENAME COLUMN new_trip_start_timestamp TO trip_start_timestamp,
    RENAME COLUMN new_trip_end_timestamp TO trip_end_timestamp;

CREATE SEARCH INDEX tt_pk_index    -- 主キーにインデックスを張る。
    ON taxi_dataset.TaxiTrip(trip_id);


Taxi Trips (2013-2023), Redshift Serverless



CREATE DATABASE taxi_database;

CREATE TABLE IF NOT EXISTS
    taxi_database.public.TaxiTrip (
        trip_id CHAR(40),
        taxi_id CHAR(128),
        trip_start_timestamp TIMESTAMP,
        trip_end_timestamp TIMESTAMP,
        trip_seconds INT,
        trip_miles FLOAT,
        pickup_census_tract VARCHAR(255),
        dropoff_census_tract VARCHAR(255),
        pickup_community_area INT,
        dropoff_community_area INT,
        fare FLOAT,
        tips FLOAT,
        tolls FLOAT,
        extras FLOAT,
        trip_total FLOAT,
        payment_type VARCHAR(64),
        company VARCHAR(255),
        pickup_centroid_latitude FLOAT,
        pickup_centroid_longitude FLOAT,
        pickup_centroid_location GEOMETRY,
        dropoff_centroid_latitude FLOAT,
        dropoff_centroid_longitude FLOAT,
        dropoff_centroid_location GEOMETRY,
        PRIMARY KEY(trip_id)
    )
    BACKUP NO
    COMPOUND SORTKEY(trip_start_timestamp, trip_end_timestamp);    -- タイムスタンプ列をソートキーにする。

COPY taxi_database.public.TaxiTrip (
        trip_id, taxi_id, trip_start_timestamp, trip_end_timestamp, trip_seconds, trip_miles, 
        pickup_census_tract, dropoff_census_tract, pickup_community_area, dropoff_community_area, 
        fare, tips, tolls, extras, trip_total, payment_type, company, 
        pickup_centroid_latitude, pickup_centroid_longitude, pickup_centroid_location, 
        dropoff_centroid_latitude, dropoff_centroid_longitude, dropoff_centroid_location
    )
FROM 's3://my-bucket-name/TaxiTrip.csv.gz'
IAM_ROLE 'my-role-arn'
REGION 'ap-northeast-1'
CSV
DELIMITER ','
NULL AS ''
IGNOREHEADER 1
TIMEFORMAT 'MM/DD/YYYY HH:MI:SS AM'
GZIP;

VACUUM;


Amazon-Reviews-2023, BigQuery



CREATE SCHEMA amazon_reviews_dataset 
    OPTIONS(
        location='asia-northeast1',
        storage_billing_model='LOGICAL'
    );

CREATE TABLE amazon_reviews_dataset.ItemMetadata (
    main_category STRING
    , title STRING
    , average_rating FLOAT64
    , rating_number INT
    , features ARRAY
    , description ARRAY
    , price FLOAT64
    , images ARRAY>
    , videos ARRAY> 
    , store STRING
    , categories ARRAY
    , details JSON
    , parent_asin STRING 
    , bought_together ARRAY
    , PRIMARY KEY(parent_asin) NOT ENFORCED
);

/*
ItemMetadataのみ、スキーマ自動検出でエラーが出るので、スキーマ自動検出をオフにするため、SQLではなく以下のbqコマンドでロードする。

$ bq --location=asia-northeast1 load \
--noautodetect --source_format=NEWLINE_DELIMITED_JSON \
amazon_reviews_dataset.ItemMetadata \
gs://my-bucket-name/item_metadata.jsonl
*/

CREATE SEARCH INDEX im_pk_index    -- 主キーにインデックスを張る。
    ON amazon_reviews_dataset.ItemMetadata(parent_asin);

CREATE TABLE amazon_reviews_dataset.UserReviews (
    rating FLOAT64
    , title STRING
    , text STRING 
    , images ARRAY>
    , asin STRING
    , parent_asin STRING 
    , user_id STRING
    , timestamp INT -- UNIX時刻。
    , verified_purchase BOOLEAN
    , helpful_vote INT
    , PRIMARY KEY(parent_asin, user_id) NOT ENFORCED
    , FOREIGN KEY(parent_asin) REFERENCES amazon_reviews_dataset.ItemMetadata(parent_asin) NOT ENFORCED
);

LOAD DATA INTO amazon_reviews_dataset.UserReviews
FROM FILES (
    format='NEWLINE_DELIMITED_JSON',
    ignore_unknown_values=true,
    uris=['gs://my-bucket-name/user_reviews.jsonl']
);

CREATE SEARCH INDEX ur_pk_index    -- 主キーにインデックスを張る。
    ON amazon_reviews_dataset.UserReviews(parent_asin, user_id);


Amazon-Reviews-2023, Redshift Serverless

Item Metadata の description は本来SUPER型ですが、サイズが大き過ぎてCOPY時にエラーが出るデータがいくつもあります。サイズの限度で打ち切るため、COPY時に TRUNCATECOLUMNS オプションを付け、SUPER型は TRUNCATECOLUMNS の対象にならないため VARCHAR(65535) 型で定義しました。この処理を施してもデータサイズはほぼ変化せず、クエリに description を使うこともないため、測定に問題はありません。



CREATE DATABASE amazon_reviews_database;

CREATE TABLE IF NOT EXISTS
    amazon_reviews_database.public.ItemMetadata (
        main_category VARCHAR(64)
        , title VARCHAR(4096)
        , average_rating FLOAT
        , rating_number INT
        , features SUPER
        , description VARCHAR(65535)
        , price VARCHAR(64)
        , images SUPER
        , videos SUPER
        , store VARCHAR(4096)
        , categories SUPER
        , details SUPER
        , parent_asin VARCHAR(16)
        , bought_together SUPER
        , PRIMARY KEY(parent_asin)
    )
    BACKUP NO;

COPY amazon_reviews_database.public.ItemMetadata (
        main_category, title, average_rating, rating_number, features, description, price,
        images, videos, store, categories, details, parent_asin, bought_together    
    )
FROM 's3://my-bucket-name/item_metadata.jsonl.gz'
IAM_ROLE 'my-role-arn'
REGION 'ap-northeast-1'
JSON 'auto'
NULL AS ''
TRUNCATECOLUMNS
GZIP;

CREATE TABLE IF NOT EXISTS 
    amazon_reviews_database.public.UserReviews (
        rating FLOAT
        , title VARCHAR(4096)
        , text VARCHAR(65535)
        , images SUPER
        , asin VARCHAR(16)
        , parent_asin VARCHAR(16)
        , user_id VARCHAR(128)
        , timestamp BIGINT
        , verified_purchase BOOLEAN
        , helpful_vote INT
        , FOREIGN KEY(parent_asin) REFERENCES ItemMetadata(parent_asin)
    )
    BACKUP NO
    COMPOUND SORTKEY(timestamp);

COPY amazon_reviews_database.public.UserReviews (
        rating, title, text, images, asin,
        parent_asin, user_id, timestamp, verified_purchase, helpful_vote 
    )
FROM 's3://my-bucket-name/user_reviews.jsonl.gz'
IAM_ROLE 'my-role-arn'
REGION 'ap-northeast-1'
JSON 'auto'
NULL AS ''
TRUNCATECOLUMNS
GZIP;

VACUUM;


計測記録の取得(BigQuery)

Redshiftではコンソール上で記録を閲覧するため、コードがありません。



SELECT
    job_id  -- クエリの一意ID。
    , TIMESTAMP_DIFF(end_time, start_time, MILLISECOND) AS elapsed_time_milliseconds  -- 応答時間(ミリ秒)。
    , total_slot_ms / TIMESTAMP_DIFF(end_time, start_time, MILLISECOND) AS num_slot  -- 「容量コンピューティング」の場合のスロット数。
    , 0.051 * total_slot_ms / (1000 * 60 * 60) AS cost_capacity  -- 「容量コンピューティング」の場合の課金額(USD)。
    , total_bytes_billed * POW(2, -40) AS total_terabytes_billed  -- スキャンされたデータ容量(TiB)。
    , 7.5 * total_bytes_billed * POW(2, -40) AS cost_on_demand  -- 「オンデマンド」の場合の課金額(USD)。
    , start_time  -- クエリの開始時刻。
    , state  -- クエリの状態(実行中でないか確認するために出力させる)
    , LEFT(query, 50)  -- クエリ文の冒頭50文字。
FROM `my-project-name`.`region-asia-northeast1`.INFORMATION_SCHEMA.JOBS_BY_PROJECT
ORDER BY start_time DESC;


リザルトキャッシュの無効化(Redshift Serverless)

BigQueryではコンソール上で設定を行うため、コードがありません。



SET enable_result_cache_for_session TO off;  -- 無効化。

SHOW enable_result_cache_for_session;  -- 無効化されていることの確認。


クエリ1-1:小規模構造化データ、単純集計

データセットに含まれる運行の総数と、運賃の平均値を求めます。

BigQuery



SELECT 
    COUNT(*) AS num_trips, 
    AVG(fare) AS avg_fare
FROM taxi_dataset.TaxiTrip;


Redshift



SELECT 
    COUNT(*) AS num_trips, 
    AVG(fare) AS avg_fare
FROM TaxiTrip;


クエリ1-2:小規模構造化データ、集計+ウィンドウ関数

1台のタクシーが1日に乗車された回数のTOP10と、その日付を調べます。


BigQuery



SELECT
    RANK() OVER (ORDER BY COUNT(trip_id) DESC) AS ranking,
    LEFT(taxi_id, 10) AS short_taxi_id,
    CAST(trip_start_timestamp AS DATE) AS date,
    COUNT(trip_id) AS trip_count
FROM taxi_dataset.TaxiTrip
GROUP BY
    CAST(trip_start_timestamp AS DATE), 
    taxi_id
ORDER BY ranking ASC
LIMIT 10;


Redshift



SELECT
    RANK() OVER (ORDER BY COUNT(trip_id) DESC) AS ranking,
    LEFT(taxi_id, 10) AS short_taxi_id,
    CAST(trip_start_timestamp AS DATE) AS date,
    COUNT(trip_id) AS trip_count
FROM TaxiTrip
GROUP BY
    CAST(trip_start_timestamp AS DATE), 
    taxi_id
ORDER BY ranking ASC
LIMIT 10;


クエリ1-3:小規模構造化データ、ウィンドウ関数+CTE+集計

「タクシーは、どの程度スムーズに乗客を見つけられるのか?」を知りたいとします。一つの指標として、「前の乗客を降ろした場所の近くで、すぐに次の乗客を拾うという事象」について調べます。1人目の客を降ろした直後にその近くで2人目の客を拾い、2人目の客を降ろした直後にその近くで3人目の客を拾い......と、この事象は連続することがあります。n回連続した事象を series n trip、n回以上連続した事象を series n or more trip と呼び、n = 1, 2, 3 について相対度数を算出します。


BigQuery



-- タクシーごとに、各運行とその直前の運行の、運行ID、開始/終了座標、開始/終了時刻を取得するCTE。
WITH CurrAndPrevTrips AS (
    SELECT
        trip_id AS curr_trip_id,
        LAG(trip_id, 1) OVER W AS prev_trip_id,
        pickup_centroid_location AS curr_start_point,
        ST_GeogFromText(
            LAG(ST_AsText(dropoff_centroid_location), 1) OVER W    -- 地理データに直接ウィンドウ関数を適用できないRedshiftに合わせた処理(本来BigQueryでは不要)。
        ) AS prev_end_point,
        trip_start_timestamp AS curr_start_time, 
        LAG(trip_end_timestamp, 1) OVER W AS prev_end_time
    FROM taxi_dataset.TaxiTrip
    WHERE
        ST_Distance(pickup_centroid_location, dropoff_centroid_location) 
            < trip_miles * 1609 -- 誤った位置情報を持っている可能性が高いレコードが15%程度あるので、除外する。
    WINDOW W AS (
        PARTITION BY taxi_id
        ORDER BY trip_start_timestamp, trip_end_timestamp, trip_id
    )
),
-- 客を降ろしてから、一定の時間・距離内で、新しい客を拾った運行(series 1 trip)の組を取得するCTE。
Series1Trips AS (
    SELECT
        curr_trip_id,
        prev_trip_id
    FROM CurrAndPrevTrips
    WHERE
        TIMESTAMP_DIFF(curr_start_time, prev_end_time, MINUTE) <= 15
        AND ST_Distance(curr_start_point, prev_end_point) < 500
),
Series2Trips AS (
    SELECT
        Tbl1.curr_trip_id AS curr_trip_id,
        Tbl1.prev_trip_id AS prev1_trip_id,
        Tbl2.prev_trip_id AS prev2_trip_id
    FROM 
        Series1Trips AS Tbl1
        INNER JOIN Series1Trips AS Tbl2
            ON Tbl1.prev_trip_id = Tbl2.curr_trip_id -- 連続している2つのうち前者が、別の連続の後者として存在している場合を捉えて結合する。以下同様。
),
Series3Trips AS (
    SELECT
        S2.curr_trip_id AS curr_trip_id,
        S2.prev1_trip_id AS prev1_trip_id,
        S2.prev2_trip_id AS prev2_trip_id,
        S1.prev_trip_id AS prev3_trip_id
    FROM 
        Series2Trips AS S2
        INNER JOIN Series1Trips AS S1
            ON S2.prev2_trip_id = S1.curr_trip_id
),
Series4Trips AS (
    SELECT S3.curr_trip_id
    FROM 
        Series3Trips AS S3
        INNER JOIN Series1Trips AS S1
            ON S3.prev3_trip_id = S1.curr_trip_id
),
-- 総運行数とn連続運行数を集計するCTE。
DuplicatedCounts AS (
    SELECT 
        (SELECT COUNT(*) FROM CurrAndPrevTrips) AS num_all_trips,
        (SELECT COUNT(*) FROM Series1Trips) AS s1, -- この数は、series 2 trip を重複して2回数えている(一般に series n trip を重複してn回数えている)。
        (SELECT COUNT(*) FROM Series2Trips) AS s2, -- この数は、series 3 trip を重複して2回数えている(一般に series n trip を重複してn-1回数えている)。以下同様。
        (SELECT COUNT(*) FROM Series3Trips) AS s3,
        (SELECT COUNT(*) FROM Series4Trips) AS s4
)
SELECT
    num_all_trips,
    s1 - s2 AS num_series_1_or_more_trips, -- この数は、series n trip を重複なく1回として数えている。以下同様。
    s2 - s3 AS num_series_2_or_more_trips,
    s3 - s4 AS num_series_3_or_more_trips,
    FORMAT('%.2f %%', (s1 - s2) / (num_all_trips * 1.0) * 100) AS rate_series_1_or_more_trips, -- 1.0 を掛けるのは、実数除算を行うための措置。以下同様。
    FORMAT('%.2f %%', (s2 - s3) / (num_all_trips * 1.0) * 100) AS rate_series_2_or_more_trips,
    FORMAT('%.2f %%', (s3 - s4) / (num_all_trips * 1.0) * 100) AS rate_series_3_or_more_trips
FROM DuplicatedCounts;


Redshift



-- タクシーごとに、各運行とその直前の運行の、運行ID、開始/終了座標、開始/終了時刻を取得するCTE。
WITH CurrAndPrevTrips AS (
    SELECT
        trip_id AS curr_trip_id,
        LAG(trip_id, 1) OVER (
            PARTITION BY taxi_id
            ORDER BY trip_start_timestamp, trip_end_timestamp, trip_id
        ) AS prev_trip_id,
        pickup_centroid_location AS curr_start_point,
        ST_GeomFromText(LAG(ST_AsText(dropoff_centroid_location), 1) OVER (  -- Redshift では、地理データに直接ウィンドウ関数を適用できない。
            PARTITION BY taxi_id
            ORDER BY trip_start_timestamp, trip_end_timestamp, trip_id
        )) AS prev_end_point,
        trip_start_timestamp AS curr_start_time, 
        LAG(trip_end_timestamp, 1) OVER (
            PARTITION BY taxi_id
            ORDER BY trip_start_timestamp, trip_end_timestamp, trip_id
        ) AS prev_end_time
    FROM TaxiTrip
    WHERE
        ST_Distance(pickup_centroid_location, dropoff_centroid_location) 
            < trip_miles * 1609 -- 誤った位置情報を持っている可能性が高いレコードが15%程度あるので、除外する。
),
-- 客を降ろしてから、一定の時間・距離内で、新しい客を拾った運行(series 1 trip)の組を取得するCTE。
Series1Trips AS (
    SELECT
        curr_trip_id,
        prev_trip_id
    FROM CurrAndPrevTrips
    WHERE
        (EXTRACT(EPOCH FROM curr_start_time) - EXTRACT(EPOCH FROM prev_end_time)) / 60 <= 15
        AND ST_Distance(curr_start_point, prev_end_point) < 500
),
Series2Trips AS (
    SELECT
        Tbl1.curr_trip_id AS curr_trip_id,
        Tbl1.prev_trip_id AS prev1_trip_id,
        Tbl2.prev_trip_id AS prev2_trip_id
    FROM 
        Series1Trips AS Tbl1
        INNER JOIN Series1Trips AS Tbl2
            ON Tbl1.prev_trip_id = Tbl2.curr_trip_id -- 連続している2つのうち前者が、別の連続の後者として存在している場合を捉えて結合する。以下同様。
),
Series3Trips AS (
    SELECT
        S2.curr_trip_id AS curr_trip_id,
        S2.prev1_trip_id AS prev1_trip_id,
        S2.prev2_trip_id AS prev2_trip_id,
        S1.prev_trip_id AS prev3_trip_id
    FROM 
        Series2Trips AS S2
        INNER JOIN Series1Trips AS S1
            ON S2.prev2_trip_id = S1.curr_trip_id
),
Series4Trips AS (
    SELECT S3.curr_trip_id
    FROM 
        Series3Trips AS S3
        INNER JOIN Series1Trips AS S1
            ON S3.prev3_trip_id = S1.curr_trip_id
),
-- 総運行数とn連続運行数を集計するCTE。
DuplicatedCounts AS (
    SELECT 
        (SELECT COUNT(*) FROM CurrAndPrevTrips) AS num_all_trips,
        (SELECT COUNT(*) FROM Series1Trips) AS s1, -- この数は、series 2 trip を重複して2回数えている(一般に series n trip を重複してn回数えている)。
        (SELECT COUNT(*) FROM Series2Trips) AS s2, -- この数は、series 3 trip を重複して2回数えている(一般に series n trip を重複してn-1回数えている)。以下同様。
        (SELECT COUNT(*) FROM Series3Trips) AS s3,
        (SELECT COUNT(*) FROM Series4Trips) AS s4
)
SELECT
    num_all_trips,
    s1 - s2 AS num_series_1_or_more_trips, -- この数は、series n trip を重複なく1回として数えている。以下同様。
    s2 - s3 AS num_series_2_or_more_trips,
    s3 - s4 AS num_series_3_or_more_trips,
    TO_CHAR((s1 - s2) / (num_all_trips * 1.0) * 100, 'FM999.000') || ' %' AS rate_series_1_or_more_trips, -- 1.0 を掛けるのは、実数除算を行うための措置。以下同様。
    TO_CHAR((s2 - s3) / (num_all_trips * 1.0) * 100, 'FM999.000') || ' %' AS rate_series_2_or_more_trips,
    TO_CHAR((s3 - s4) / (num_all_trips * 1.0) * 100, 'FM999.000') || ' %' AS rate_series_3_or_more_trips
FROM DuplicatedCounts;


クエリ2-1:中規模半構造化データ、CTE+集計

Amazonレビューが「参考になった」を獲得する数に関して分析したいとします。一般に、投稿された直後のレビューは「参考になった」を獲得しておらず、時間の経過とともに獲得数を増やし、十分時間が経過することでそのレビューに相応しい獲得数に漸近すると考えられます。そこで分析の際、「十分時間」が経過していないレビューをWHERE句で排除することで、獲得数が安定したデータのみを対象にできます。そのためにここでは、「十分時間」が何年であるか特定するため、レビューを経過年数の階級に分類し、階級ごとに獲得数の平均値を求めます。そして階級の平均値と全体の平均値の比を取り、その比が一定の閾値に達しているかどうかのフラグを出力させます。

このデータセットのタイムスタンプはミリ秒単位のUNIX時刻です。このデータが収集されたのは2023年9月23日で、UNIX時刻にすると1695427200000になります。


BigQuery



WITH VoteNumWithClass AS (
    SELECT
        helpful_vote
        , CASE
            WHEN timestamp > 1679529600000 THEN '0.0-0.5y'  -- 投稿から経過した時間が0年以上半年未満である階級。以下同様。
            WHEN timestamp > 1663891200000 THEN '0.5-1.0y'
            WHEN timestamp > 1647993600000 THEN '1.0-1.5y'
            WHEN timestamp > 1632355200000 THEN '1.5-2.0y'
            WHEN timestamp > 1616457600000 THEN '2.0-2.5y'
            WHEN timestamp > 1600819200000 THEN '2.5-3.0y'
            WHEN timestamp > 1584921600000 THEN '3.0-3.5y'
            WHEN timestamp > 1569196800000 THEN '3.5-4.0y'
            WHEN timestamp > 1553299200000 THEN '4.0-4.5y'
            WHEN timestamp > 1537660800000 THEN '4.5-5.0y'
            WHEN timestamp <= 1537660800000 THEN '5.0y-'
            ELSE NULL
        END AS class
        , AVG(helpful_vote) OVER () AS overall_avg
    FROM amazon_reviews_dataset.UserReviews
)
SELECT
    class
    , AVG(helpful_vote) / MAX(overall_avg) AS votes_ratio_to_overall
    , CASE
        WHEN AVG(helpful_vote) / MAX(overall_avg) < 0.7
        THEN 'Too recent to rely on.'
        ELSE 'Old enough.'
    END AS eval_usable_or_not
FROM VoteNumWithClass
GROUP BY class
ORDER BY class;


Redshift



WITH VoteNumWithClass AS (
    SELECT
        helpful_vote
        , CASE
            WHEN timestamp > 1679529600000 THEN '0.0-0.5y'  -- 投稿から経過した時間が0年以上半年未満である階級。以下同様。
            WHEN timestamp > 1663891200000 THEN '0.5-1.0y'
            WHEN timestamp > 1647993600000 THEN '1.0-1.5y'
            WHEN timestamp > 1632355200000 THEN '1.5-2.0y'
            WHEN timestamp > 1616457600000 THEN '2.0-2.5y'
            WHEN timestamp > 1600819200000 THEN '2.5-3.0y'
            WHEN timestamp > 1584921600000 THEN '3.0-3.5y'
            WHEN timestamp > 1569196800000 THEN '3.5-4.0y'
            WHEN timestamp > 1553299200000 THEN '4.0-4.5y'
            WHEN timestamp > 1537660800000 THEN '4.5-5.0y'
            WHEN timestamp <= 1537660800000 THEN '5.0y-'
            ELSE NULL
        END AS class
        , AVG(helpful_vote) OVER () AS overall_avg
    FROM UserReviews
)
SELECT
    class
    , AVG(helpful_vote) / MAX(overall_avg) AS votes_ratio_to_overall
    , CASE
        WHEN AVG(helpful_vote) / MAX(overall_avg) < 0.7
        THEN 'Too recent to rely on.'
        ELSE 'Old enough.'
    END AS eval_usable_or_not
FROM VoteNumWithClass
GROUP BY class
ORDER BY class;


クエリ2-2:中規模半構造化データ、JOIN+集計

商品のレビュー数が多くなると、「自分がレビューを書く意味がない」と感じる人が増えて、レビュー数の増加が鈍化する傾向がある、という推測を立てました。これについて調査したいと思います。しかし、単にレビュー数の時間変化率だけを見ると、その商品が人気を失ってレビューされなくなった場合と区別できません。また、サクラを利用していたり、クーポンなどの報酬を用意して購入者にレビューを書くよう促したりしている商品であれば、通常のレビュー数の鈍化パターンに当てはまらないだろうと思われます。

そこでこのクエリでは、「商品ID、商品のレビュー数、商品のレビューについた『参考になった』の総数」の組を取得します。十分なレビュー数がある商品のうち、レビュー数に対して「参考になった」総数が多いものは、鈍化傾向にある可能性が高く、逆に少ないものはサクラなどを利用している可能性が高いと考えられます。

結果セットのサイズが大きいので、Redshiftでは一時テーブルに出力して表示させることができません。UNLOADコマンドによってS3バケットに結果を出力します。


BigQuery



SELECT
    UR.parent_asin
    , MAX(IM.rating_number) AS rating_number -- 1つの parent_asin に対応する rating_number は一意。このMAX関数は形式的なもので、実際は唯一の rating_number が返される。
    , SUM(UR.helpful_vote) AS sum_vote
FROM
    amazon_reviews_dataset.UserReviews UR 
    INNER JOIN amazon_reviews_dataset.ItemMetadata IM
        ON UR.parent_asin = IM.parent_asin
GROUP BY UR.parent_asin;


Redshift



UNLOAD('
    SELECT
        UR.parent_asin
        , MAX(IM.rating_number) AS rating_number -- 1つの parent_asin に対応する rating_number は一意。このMAX関数は形式的なもので、実際は唯一の rating_number が返される。
        , SUM(UR.helpful_vote) AS sum_vote
    FROM
        UserReviews UR 
        INNER JOIN ItemMetadata IM
            ON UR.parent_asin = IM.parent_asin
    GROUP BY UR.parent_asin;
')
TO 's3://my-bucket-name/unload2-2/'
IAM_ROLE 'my-role-arn'


クエリ2-3:中規模半構造化データ、ウィンドウ関数集計+CTE+JOIN

「参考になった」を獲得しやすい、優れたレビューの特徴を分析したいとします。そのためのデータを、2-1で求めた期間の条件でフィルタリングし、適切に加工して取り出す必要があります。しかし、単純に「参考になった」の獲得数を基準とするのは不適切だと考えられます。100件以上の「参考になった」を獲得しているレビューが複数ある商品で10件の「参考になった」を獲得しているレビューと、他に「参考になった」を獲得しているレビューが存在しない商品で10件獲得しているレビューでは、後者をより「優れている」と判定すべきだからです。

そこでこの分析では、パレート分析のような方法を用いることにしました。具体的には、商品ごとに、「参考になった」獲得数の順にレビューを並べ、累積相対度数に応じてグループA、B、Cに分けます(総度数が0の場合のグループはNULLとします)。そしてレビューごとに、そのレビューがどのグループに属するかと、以下の情報をセットにして出力します(後工程で、レビューがどのグループになるかを説明できる変数の組み合わせを探るという想定):「商品ID」、「評価値(星の数)」、「商品全体の平均評価値と評価値の差」、「添付画像の有無」、「レビュータイトルの原文」、「レビュータイトルの単語数」、「レビュー本文の原文」、「レビュー本文の単語数」。

結果セットのサイズが大きいので、一時テーブルに出力して表示させることができません。BigQueryでは別のテーブルを作成した上でそこに結果を保存する設定を行い、RedshiftではUNLOADコマンドによってS3バケットに結果を出力します。


BigQuery



WITH UserReviewWithWindow AS (
    SELECT
        *
        , 1.0 * SUM(UR.helpful_vote) OVER (
            PARTITION BY UR.parent_asin
            ORDER BY UR.helpful_vote DESC
        ) -- 商品ごとに、「参考になった」数の多い順にレビューを並べたときの、「参考になった」の累積度数。1.0を掛けるのは商を浮動小数点値にするため。
            / NULLIF(SUM(UR.helpful_vote) OVER (PARTITION BY UR.parent_asin), 0) -- 商品ごとの「参考になった」合計数。これで割ることで、「参考になった」の累積相対度数になる。
            AS crf
        , RANK() OVER (
            PARTITION BY UR.parent_asin
            ORDER BY UR.helpful_vote DESC
        ) AS rank -- 商品ごとに、「参考になった」数の多い順にレビューを並べたときの順位。
    FROM amazon_reviews_dataset.UserReviews UR
    WHERE UR.timestamp < 1584921600000 -- 2−1で決まったUNIX時刻(3年以上経過)。
)
SELECT
    UR.parent_asin -- 商品ID。
    , CASE -- パレート分析のグループを割り当てる。70%までをAグループ、90%までをBグループ、以降をCグループとする。
        WHEN UR.rank = 1 AND UR.crf IS NOT NULL THEN 'A' -- 相対度数が0.7以上のレビューをAグループに割り振るための処理。
        WHEN UR.crf < 0.7 THEN 'A'
        WHEN UR.crf < 0.9 THEN 'B'
        WHEN UR.crf <= 1.0 THEN 'C'
        ELSE NULL
    END AS pareto_group
    , UR.rating
    , IM.average_rating - UR.rating AS diff_avg_rating
    , CASE
        WHEN ARRAY_LENGTH(UR.images) = 0
        THEN false
        ELSE true
    END AS has_images
    , UR.title AS raw_title
    , LENGTH(UR.title) - LENGTH(REPLACE(UR.title, ' ', '')) + 1 AS num_words_title
    , UR.text AS raw_text
    , LENGTH(UR.text) - LENGTH(REPLACE(UR.text, ' ', '')) + 1 AS num_words_text
FROM
    UserReviewWithWindow UR 
    INNER JOIN amazon_reviews_dataset.ItemMetadata IM 
        ON UR.parent_asin = IM.parent_asin;


Redshift



UNLOAD('
    WITH UserReviewWithWindow AS (
        SELECT
            *
            , 1.0 * SUM(UR.helpful_vote) OVER (
                PARTITION BY UR.parent_asin
                ORDER BY UR.helpful_vote DESC
                ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING  -- Redshift では集約ウィンドウ関数に ORDER BY 句を含める場合、フレーム句が必須。
            ) -- 商品ごとに、「参考になった」数の多い順にレビューを並べたときの、「参考になった」の累積度数。1.0を掛けるのは商を浮動小数点値にするため。
                / NULLIF(SUM(UR.helpful_vote) OVER (PARTITION BY UR.parent_asin), 0) -- 商品ごとの「参考になった」合計数。これで割ることで、「参考になった」の累積相対度数になる。
                AS crf
            , RANK() OVER (
                PARTITION BY UR.parent_asin
                ORDER BY UR.helpful_vote desc
            ) AS rank -- 商品ごとに、「参考になった」数の多い順にレビューを並べたときの順位。
        FROM UserReviews UR
        WHERE timestamp < 1584921600000 -- 2-1で決まったUNIX時刻(3年以上経過)。
    )
    SELECT
        UR.parent_asin -- 商品ID。
        , CASE -- パレート分析のグループを割り当てる。70%までをAグループ、90%までをBグループ、以降をCグループとする。
            WHEN UR.rank = 1 AND UR.crf IS NOT NULL THEN ''A'' -- 相対度数が0.7以上のレビューをAグループに割り振るための処理。
            WHEN UR.crf < 0.7 THEN ''A''
            WHEN UR.crf < 0.9 THEN ''B''
            ELSE ''C''
        END AS pareto_group
        , UR.rating
        , IM.average_rating - UR.rating AS diff_avg_rating
        , CASE
            WHEN GET_ARRAY_LENGTH(UR.images) = 0
            THEN false
            ELSE true
        END AS has_images
        , UR.title AS raw_title
        , LENGTH(UR.title) - LENGTH(REPLACE(UR.title, '' '', '''')) + 1 AS num_words_title
        , UR.text AS raw_text
        , LENGTH(UR.text) - LENGTH(REPLACE(UR.text, '' '', '''')) + 1 AS num_words_text
    FROM
        UserReviewWithWindow UR
        INNER JOIN ItemMetadata IM 
            ON UR.parent_asin = IM.parent_asin;
')
TO 's3://my-bucket-name/unload2-3/'
IAM_ROLE 'my-role-arn'




X(旧Twitter)・Facebookで定期的に情報発信しています!

VMwareからAWSへの移行について

  1. 導入
  2. 移行のステップ
  3. 移行戦略のパターン
  4. 移行後のアーキテクチャ
  5. 移行の成功事例
  6. まとめ


本記事では、VMware環境からAWSへの移行手順・移行の進め方・構成決定方法・成功事例について紹介します。


1. 導入

近年、クラウド移行を検討する企業が増える中で、VMware環境からAWS(Amazon Web Services)への移行が特に注目されています。特に、2024年に実施されたVMwareのライセンス料金改定が移行の大きな動機になっているケースが増加しています。多くの企業が、VMwareのライセンスやサポート料金の上昇に直面し、よりコスト効率の良いAWSへの移行を検討するようになりました。

VMwareからAWSへの移行は、単にコスト削減だけでなく、AWSのスケーラビリティや柔軟性、そしてクラウドネイティブのサービスを最大限に活用できる点でも有利です。本記事では、VMware環境からAWSへ移行するための具体的な手順と、移行後の最適化について詳しく解説します。


2. 移行のステップ

クラウドへの移行は、単にシステムを移すだけではなく、移行後の最適化と運用の効率化が重要です。以下のステップに分けて、移行プロセス全体を進めることが推奨されます。

移行のステップ


2-1. 現状(クラウド移行決定前)評価

移行を検討する際は、まず現状のオンプレミス環境やVMware環境をしっかりと評価する必要があります。この評価では、移行候補となるアプリケーションやシステムがクラウド環境に最適かどうか、またどの移行戦略(Rehost、Replatform、Refactor)が最も適切かを判断します。

特に考慮すべき点は以下の通りです

  • アプリケーションの互換性:AWS上で問題なく動作するかどうか
  • コスト試算:オンプレミスとクラウドのコスト比較
  • セキュリティ要件:クラウド移行後のデータ保護やコンプライアンス対応


2-2. 移行計画

次に、評価結果に基づいて詳細な移行計画を立てます。この段階では、各ステークホルダーとのコミュニケーションが重要です。移行に伴うダウンタイムや、システムの変更点、各チームの役割分担を明確にする必要があります。


2-3. 移行実施と最適化

移行の実施では、計画通りにリフト&シフト、またはリファクター等のアプローチに従ってシステムをAWSに移行します。移行後は、AWSのサービスを最大限に活用し、システムのパフォーマンスやコストの最適化を行うことが重要です。

移行後の最適化には、次のような具体的な作業があります。

  • リソースのモニタリング:AWSのCloudWatchなどを使用して、システムのパフォーマンスやリソース使用率を常時監視し、必要に応じて調整を行います。
  • コスト管理の最適化:AWS Cost ExplorerやTrusted Advisorを活用して、不要なリソースやコスト削減の余地を特定し、運用コストの削減を図ります。
  • セキュリティ強化:AWSのセキュリティツール(AWS Identity and Access Management、AWS Shieldなど)を使い、移行後のデータ保護やアクセス管理を強化します。


3. 移行戦略のパターン

移行を進める前に、まずいくつかの移行戦略を把握する必要があります。

VMwareからAWSへの移行にはいくつかのアプローチがあります。

3-1. Rehost(リホスト、リフト&シフト)

Rehostは、リフト&シフトとして知られ、既存のVMware環境で稼働している仮想マシンをAWS上にそのまま移行する方法です。この方法では、仮想マシン(VM)をほぼそのままAWSのEC2インスタンスに移すため、アプリケーションのコードやアーキテクチャを変更する必要がありません。

メリットとしては、移行が比較的簡単かつ迅速に行えることや、移行中のリスクが低いことが挙げられます。一方で、デメリットとしては、AWSのスケーラビリティやコスト最適化機能を最大限に活用できない場合があるため、クラウドに最適化されていない構成になりやすい点があります。


3-2. Replatform(リプラットフォーム)

Replatformは、「リフト、ティンカー、アンドシフト」とも呼ばれ、既存のアプリケーションをAWSのクラウドサービスに最適化するアプローチです。この方法では、アプリケーションの基本的なアーキテクチャを維持しつつ、データベースをAmazon RDSに移行するなど、一部のサービスやコンポーネントをクラウドネイティブなものに置き換えます。

メリットとして、完全にアプリケーションを再設計する必要がないため、ある程度効率的にクラウド最適化が行え、クラウド特有の利点を享受できます。デメリットは、変更箇所によってはある程度のコストや時間がかかること、特に検証やテストに手間がかかる点です。


3-3. Refactor(リファクター、再アーキテクチャ)

Refactorは、アプリケーションを完全にクラウド向けに再設計する移行アプローチです。アプリケーション全体を再アーキテクチャし、クラウドネイティブな技術(例えばサーバーレスアーキテクチャやマイクロサービス)を導入することで、AWSの柔軟性やコスト効率を最大限に活用します。

メリットは、アプリケーションのパフォーマンス向上やコスト削減、可用性の向上が期待できる点です。また、AWSの豊富なサービスを活用して、アプリケーションのスケーラビリティを高めることができます。デメリットとしては、アプリケーションの再設計や再開発が必要になるため、時間とコストが大幅にかかる可能性がある点です。

移行戦略を検討する際には、以下の観点を考慮して決定する必要があります。

  • Rehostは、最も簡単なアプローチで、迅速に移行を行いたい場合に適していますが、クラウドの特性を最大限に活かすには限界があります。
  • Replatformは、最低限の変更でクラウドのメリットを部分的に享受でき、よりバランスの取れた選択肢です。
  • Refactorは、クラウドネイティブな技術をフル活用できる最も柔軟で効率的な方法ですが、移行の複雑さが増します。


4. 移行後のアーキテクチャ

移行を決めると、どのようなアーキテクチャにするべきか検討します。移行先を選択する際には、大まかに下記のフローで考えることもできます。

移行検討のフロー

図にあるサービスをひとつずつ説明します。

Amazon EC2

ユースケース例: 既存のアプリケーションをほぼそのまま移行し、コスト削減したい

選択理由

  • 最小限の変更で既存のワークロードを移行したい
  • OSのバージョンを変えたくない、特定のOSやソフトウェアバージョンへの依存がある
  • ダウンタイムを最小化して移行したい
  • 段階的なクラウド移行を行いたい


移行ツール: AWS Application Migration Service (AWS MGN)、AWS Backup、VM Import/Export など


Amazon RDS

ユースケース例:データベース管理の負担を軽減したい、コストを最適化したい

選択理由

  • フルマネージドによる運用工数・コストの削減
  • ライセンスコストの最適化
  • データベースエンジンを変更せずに移行したい
  • ダウンタイムを最小化して移行したい


移行ツール: AWS Database Migration Service (AWS DMS)、Oracle Data Pump などのネイティブツール


Amazon WorkSpaces / Horizon + WorkSpaces Core

ユースケース例: 仮想デスクトップ環境 (VDI) を移行したい

選択理由

  • フルマネージドによる運用工数・コストの削減
  • 仮想デスクトップ管理を簡素化
  • コスト効率の高い料金設定
  • Horizon のユーザー体験のまま移行したい(Horizon + WorkSpaces Core)


AWS Outposts Family

ユースケース例: データレジデンシー対応、低レイテンシーが必要な場合

選択理由

  • データの所在地に厳しい規制がある
  • オンプレミスのアプリケーションと低レイテンシーでの接続、リアルタイム処理が必要
  • オンプレミス環境とAWSの一貫した管理を行いたい


移行ツール:AWS Elastic Disaster Recovery (AWS DRS) など


NC2 on AWS / ROSA

ユースケース例:仮想環境の運用体制やオペレーションを極力変えたくない

選択理由

  • 既存環境との親和性
  • 最小限の変更で既存のワークロードを移行したい
  • OSのバージョンを変えたくない、特定のOSやソフトウェアバージョンへの依存がある
  • 段階的なクラウド移行を行いたい


移行ツール:NC2 on AWS: Nutanix Move、ROSA: Migration Toolkit for Virtualization (MTV)


5. 移行の成功事例

5-1.コスト削減とパフォーマンス向上

A社では、VMware環境のライセンスコスト上昇を受けてAWSへの移行を決定しました。リフト&シフト戦略を採用し、既存のアプリケーションをAWS EC2インスタンスに移行しました。結果として、初期移行コストを抑えつつ、AWSのスケーラビリティを活用して、システムパフォーマンスを向上させることに成功しました。


5-2.リファクターで大規模なアーキテクチャ改革

B社は、クラウドネイティブな技術をフルに活用するため、既存のアプリケーションを完全にリファクターし、サーバーレスアーキテクチャに移行しました。移行後、運用効率が大幅に向上し、コスト削減と同時にアプリケーションのパフォーマンスが飛躍的に向上しました。


6. まとめ

VMwareからAWSへの移行は、コスト削減や運用効率の向上、スケーラビリティの獲得といった多くのメリットをもたらします。Rehost、Replatform、Refactorという移行戦略を適切に選び、移行後の最適化を行うことで、AWSの強力なクラウドサービスを最大限に活用することができます。

企業のITインフラを次世代にシフトさせるための一手段として、AWSへの移行をぜひ検討してみてください。




X(旧Twitter)・Facebookで定期的に情報発信しています!

  1. はじめに
  2. AWS移行のためのステップ
  3. 活用できるAWSサービス
  4. AWSとAzureの比較
  5. まとめ


1.はじめに

オンプレミス環境からクラウドに移行することは、企業にとって大きな変革の一歩です。AWS (Amazon Web Services) への移行は、コスト削減、運用効率の向上、スケーラビリティを提供するだけでなく、最新のクラウドテクノロジーを活用してビジネスを加速させる大きな機会となります。しかし、移行プロセスは複雑であり、慎重な計画と適切なツールの活用が不可欠です。本記事では、オンプレミスからAWSに移行する際の具体的な手順、活用すべきAWSサービス、Azureとの比較を含め、移行の成功を導くための実践的なガイドを提供します。


2.AWS移行のためのステップ


移行のためのステップ


移行の計画と準備

オンプレミスからAWSへの移行を成功させるための第一歩は、現状の環境を評価し、適切な移行計画を策定することです。このフェーズでは、移行対象のアプリケーションやインフラ、データを詳細に分析し、それぞれに適した移行戦略を選択する必要があります。多くの企業は「6R戦略」(Rehost、Replatform、Refactor、Retire、Retain、Repurchase)のどれが最適かを判断するために、徹底した環境分析を行います。


事例:製造業の大手企業B社のケース

B社は、オンプレミスのデータセンターをAWSに移行する際、既存のSAPシステムや社内管理ツールを考慮し、移行の計画段階から「Replatform(リプラットフォーム)」を選択しました。特に、同社のシステムは大量のデータを扱っており、パフォーマンスの低下を防ぐために、AWSのデータベースサービスへの最適化が求められました。AWS Database Migration Service (DMS) を使用して、既存のデータベースをAmazon Auroraに移行し、同時にパフォーマンスの改善も実現しています。


移行の実施

移行の実施では、選択した戦略に従って、AWSの各種移行ツールを活用し、データ、アプリケーション、ネットワークの移行を行います。以下に、主なAWSの移行サービスを紹介します。


  • AWS DataSync: オンプレミスのファイルサーバーからAWSのストレージサービス(S3やEFSなど)にデータを移行する際に使います。特に大規模データの転送において、高速かつセキュアな移行が可能です。

  • AWS Application Migration Service (MGN): 物理サーバーや複雑なアプリケーション環境を、最小のダウンタイムでAWSに移行するための強力なツールです。


事例:金融機関C社のケース

金融機関C社は、高度なセキュリティ要件を満たす必要があり、データ移行の際にAWS Snowballを使用しました。大量のデータを安全にAWSデータセンターへ物理的に移行するこのサービスにより、ネットワーク帯域の問題を解決し、機密データの安全な転送を実現しました。結果として、オンプレミスのデータセンターを閉鎖し、すべての運用をAWSの仮想環境に移行できました。


最適化

移行が完了した後は、AWSのクラウドインフラの特性を活かして運用を最適化することが重要です。AWSのCloudWatchを使用して、システムパフォーマンスのモニタリングを行い、リソースの利用状況を監視します。また、AWS Trusted Advisor や AWS Cost Explorer を使用して、コスト効率を定期的に見直し、不要なリソースを削除して運用コストを削減することが推奨されます。


3.活用できるAWSサービス

AWS DataSync

データを迅速に移行するために使用されるAWS DataSyncは、オンプレミスのストレージからAWSに大量のデータを転送する際に非常に効果的です。特に、Amazon S3やEFS、FSx for Windows File ServerなどのAWSストレージサービスとシームレスに連携するため、大規模なファイルシステムの移行に適しています。


AWS Application Migration Service (MGN)

AWS Application Migration Service (MGN)は、オンプレミスの物理サーバーや仮想マシンをリアルタイムに複製し、AWS環境にシームレスに移行するためのサービスです。リアルタイムで変更を反映するため、移行中のデータの整合性を保ち、ダウンタイムをほぼゼロに抑えることができます。


AWS Database Migration Service (DMS)

オンプレミスのデータベースからAWSのRDS、Aurora、DynamoDBなどへデータベースを移行するためのAWS Database Migration Service (DMS)は、最小限のダウンタイムで移行が可能です。特に、異なるデータベースエンジン間の移行にも対応しているため、OracleからAmazon Auroraへの移行など、移行後にコストやパフォーマンスが大幅に改善されます。


事例:EコマースD社のケース

D社は、オンプレミスのSQL ServerからAmazon Auroraに移行する際に、AWS Database Migration Service (DMS)を使用しました。この移行により、既存のデータを失うことなく、ダウンタイムを最小限に抑えたままデータベースの移行が完了しました。さらに、移行後はAmazon Auroraのスケーラビリティとコスト効率の恩恵を受け、大幅なコスト削減とパフォーマンス向上を達成しました。


4.AWSとAzureの比較

クラウド移行を検討する際、AWSとAzureの比較は重要なポイントです。それぞれの強みを理解し、適切な移行先を選択することが求められます。


AWSとAzureの比較


サービスの豊富さ

AWSは、クラウド市場のリーダーとして、最も多くのサービスとリージョンを提供しており、グローバルな企業やスタートアップまで幅広く利用されています。特に、AIや機械学習、サーバーレスアーキテクチャに強みがあります。

Azureは、特にMicrosoft製品との親和性が高く、既にWindows ServerやActive Directoryなどを使用している企業にとっては非常に強力な選択肢です。オンプレミスとクラウドのハイブリッド環境を構築するAzure Stackも大きな特徴です。


ハイブリッドクラウド対応

Azureは、オンプレミスとクラウドを統合するハイブリッドクラウド戦略に強みがあります。特に、Azure Stackにより、クラウドと同じ技術をオンプレミスでも利用できるため、既存のデータセンターとクラウドをシームレスに統合できます。

一方で、AWSも、AWS Outpostsを通じてハイブリッドクラウドをサポートしており、オンプレミス環境でもAWSと同じAPIやツールを使用してインフラを管理できます。


コストとライセンス

AWSは、従量課金制を採用しており、リザーブドインスタンスやSavings Plansによる長期的なコスト最適化が可能です。また、各種の無料利用枠を活用することで、初期コストを抑えることができます。

Azureは、特にMicrosoftの既存ライセンスを持っている場合に有利です。Azure Hybrid Benefitを使用すれば、Windows ServerやSQL Serverのライセンスコストを削減することができるため、特にMicrosoft製品を多く使用している企業には有利な選択肢です。


5.まとめ

オンプレミスからAWSへの移行は、クラウドのスケーラビリティ、柔軟性、コスト効率を最大限に活かすための第一歩です。移行の成功には、適切な計画と移行戦略、そしてAWSの豊富な移行ツールを活用することが重要です。また、AWSとAzureの比較を行い、企業のニーズに最も適したクラウドソリューションを選択することが求められます。

実際の事例を通じてわかるように、AWSの移行ツールを活用することで、大規模データや重要なアプリケーションの移行をスムーズに進め、クラウドへの移行を成功させることが可能です。クラウド移行を検討している企業は、移行後の最適化も含めて、AWSのポテンシャルを最大限に活用し、ビジネスを次のステージへと引き上げることができるでしょう。




X(旧Twitter)・Facebookで定期的に情報発信しています!

  1. はじめに
  2. クラウド運用の課題
  3. 解決方法
  4. クラウド運用の改善事例
  5. まとめ


1.はじめに

クラウドコンピューティングの普及により、多くの企業がオンプレミスのインフラからクラウド環境へと移行しています。しかし、そのメリットを享受する一方で、クラウド運用に伴う新たな課題も浮上しています。特に、コスト管理やセキュリティ、パフォーマンス最適化といった運用面の複雑さが企業にとって大きな問題となっています。本記事では、クラウド運用における主な課題と、それに対する効果的な解決方法を紹介します。


2. クラウド運用の課題


クラウド運用の課題

コスト管理の難しさ

クラウドのメリットの一つに、利用したリソースに応じた課金モデルがあります。しかし、これがかえってコストの見えにくさを引き起こす要因にもなります。特に複数のクラウドサービスを併用するマルチクラウド環境では、どのリソースがどれだけのコストを消費しているのかを把握するのが難しく、意図せぬコスト増加が発生しがちです。


クラウドリソースの無駄遣い

クラウドリソースの無駄遣いとは、使用されていないにもかかわらず停止されていないリソースが増加し、結果的にコストや管理負担が膨らむ状態を指します。これは特に大規模な開発環境や、サービス運用を長期間にわたって行う企業でよく見られる問題です。


セキュリティリスクの増加

クラウド環境に移行することで、セキュリティの責任共有モデルを理解し、オンプレミスとは異なるセキュリティ要件を管理しなければなりません。特に、クラウド上でのデータ保護、アクセス制御、コンプライアンス遵守など、セキュリティリスクに対する意識と対応が重要です。


最適なパフォーマンス維持が難しい

クラウドサービスは多くのメリットを提供しますが、パフォーマンス最適化が難しい場合があります。クラウドサービスプロバイダーが提供するインフラに依存するため、ネットワーク遅延や、キャパシティの問題が発生することがあります。また、アプリケーションの規模が大きくなると、システム全体のパフォーマンス管理が複雑化します。


3.解決方法

解決方法

クラウドコスト管理ツールの活用

クラウドコストを最適に管理するためには、コスト管理ツールの導入が効果的です。AWSのAWS Cost ExplorerやMicrosoft AzureのAzure Cost Management、Google CloudのCost Management Dashboardなどのツールを活用することで、リアルタイムのコスト分析や予算設定、コストの異常な増加を監視できます。これにより、無駄なリソースの特定や、効率的なコスト配分が実現します。


ゼロトラストアーキテクチャの導入

セキュリティリスクを軽減するためには、ゼロトラストモデルの導入が有効です。ゼロトラストアーキテクチャでは、内部外部のネットワークを問わず、すべてのアクセスを検証し、信頼できる通信のみを許可します。また、IAM(Identity and Access Management)ツールを使用し、ユーザーやデバイスのアクセス権を厳密に管理することで、セキュリティを強化できます。クラウドサービスに対して多要素認証(MFA)を導入することも有効な方法です。


リソース起動の自動化とガバナンス

クラウドリソースの無駄遣いを防ぐためには、自動化とガバナンスの強化が必要です。クラウドプロバイダーが提供するツール(例えば、AWSのAWS LambdaAuto Scaling)を活用し、使用していないリソースを自動的に削除またはスケールダウンさせる仕組みを構築しましょう。加えて、運用ポリシーやリソースの使用に関するガバナンスルールを明確に定義し、それに従うことが重要です。


パフォーマンスモニタリングの強化

クラウド上でのパフォーマンスを最適化するためには、モニタリングを強化する必要があります。クラウドサービスプロバイダーの提供するモニタリングツール(AWSのCloudWatch、AzureのAzure Monitorなど)を活用し、システム全体のパフォーマンスをリアルタイムで監視しましょう。これにより、ボトルネックを迅速に特定し、パフォーマンス向上に向けた調整を行うことができます。


インフラ改善・構築の効率化

クラウド環境を効率的に管理し、柔軟にスケールするためには、Infrastructure as Code (IaC)のアプローチが役立ちます。IaCを利用することで、インフラをコードとして管理し、再利用可能なテンプレート化による迅速なデプロイやスケーリングが可能となります。これにより、手動設定によるエラーを減らし、一貫した運用が実現できます。


4.クラウド運用の改善事例

大手Eコマース企業の事例

ある大手Eコマース企業は、急速な成長に伴い、クラウド環境の運用コストが大幅に増加していました。同社は、マルチクラウド戦略を採用していたため、リソースが適切に活用されていないことが大きな課題となっていました。

この企業は、AWS Cost Explorerを活用し、使用されていないリソースやコスト増加の要因を特定しました。その結果、未使用のリソースを削減し、クラウド環境全体でのコスト削減に成功しました。また、Infrastructure as Codeを導入することで、インフラの管理とデプロイ作業を自動化し、運用効率も向上しました。


中堅企業のセキュリティ強化事例

ある中堅企業では、従業員が多様なデバイスからクラウドにアクセスすることが増えたため、セキュリティリスクが懸念されていました。同社はゼロトラストセキュリティモデルを導入し、すべてのアクセスに対して厳格な認証を行う仕組みを構築しました。また、IAMツールと多要素認証を導入することで、セキュリティリスクを軽減しました。これにより安全なクラウド運用が可能になりました。


5.まとめ

クラウド運用には多くのメリットがある一方で、コスト管理やセキュリティ、パフォーマンス最適化など、解決すべき課題も数多く存在します。しかし、適切なツールや戦略を導入することで、これらの課題を効果的に解決し、クラウド環境を最大限に活用することが可能です。企業がクラウドの利点を活かしながら、運用を最適化するためには、継続的な改善と適切な管理体制の構築が不可欠です。

クラウド運用に関するご相談や最適化についての詳しい情報をお求めの場合は、ぜひ私たちにご連絡ください。クラウド導入から運用の最適化まで、貴社のニーズに合わせた最善のソリューションを提案いたします。




X(旧Twitter)・Facebookで定期的に情報発信しています!

目次

  1. 背景
  2. コスト削減のための分析
  3. 解決策
  4. 結果

 

背景

Amazon RDS(Relational Database Service)は、多くの企業で利用されるマネージド型データベースサービスです。高可用性や自動バックアップなどの機能を備えており、運用管理の負担を軽減しますが、使い方によってはコストが膨らみ、企業のIT予算を圧迫する原因となります。
当社でもRDSのコスト最適化に取り組み、その結果、利用コストを最大で50%削減することに成功しました。


RDSコスト削減のために改善できるポイントは以下の通りです。
1. 使用していないリソースが長期間稼働している。
2. データベースインスタンスのサイズが適切でないため、リソースが過剰に割り当てられている。
3. ストレージやバックアップが最適化されていない。
4. オンデマンド料金が高く、コストが予測しづらい。
今回は、これらの問題に対処するために行った原因調査と解決策について具体的に解説し、どのようにコスト削減を実現したかを紹介します。


コスト削減のための分析

まずは、AWS Cost Explorerを使用してRDSのコストを詳細に分析しました。


RDSのコスト構成要素

1.インスタンスの稼働料金:データベースインスタンスのサイズに応じて、時間ごとに発生。
2.ストレージ料金:データベースのストレージ容量に基づいて発生。
3.バックアップ料金:自動バックアップやスナップショットに対するストレージ料金。
4.データ転送料金:データベースから外部に出るデータの転送料。


不必要なコストの原因

1.過剰なインスタンスサイズ:使用しているインスタンスサイズが過大であり、実際のトラフィックに比べてリソースが過剰に割り当てられていた。
2.ストレージの最適化不足:必要以上に高パフォーマンスなストレージタイプを使用していた。
3.リザーブドインスタンスの未活用:オンデマンドインスタンスを利用しており、リザーブドインスタンスのディスカウントを活用していなかった。


解決策

それぞれの問題を解決するため、以下の施策を実行しました。


1. インスタンスサイズの適正化

アプローチ

RDSインスタンスのサイズを、実際のトラフィックやパフォーマンス要件に基づいて見直しました。
例えば、CPU使用率やメモリ使用量がインスタンスのスペックに比べて著しく低い場合、インスタンスを小さいものに変更することで、コストを削減できます。
以下の表のように、m5.largeからt3.mediumに変更すると、月額200USD以上のコスト削減が期待できます。

RDSインスタンスサイズによる価格表"

ポイント

オンデマンドインスタンスは、利用時間に応じて料金が発生するため、インスタンスの稼働状況に応じたリサイズを行うことで、効率的にコストを削減できます。


2. ストレージタイプの最適化

アプローチ

RDSはストレージの種類として、汎用SSD(gp2)、プロビジョンドIOPS(io1)、マグネティックなどがあります。高パフォーマンスなio1を利用していたものの、実際にはそこまでの性能が必要なかったため、汎用SSD(gp2)に変更することでストレージコストを削減しました。

500GB使う場合のそれぞれのストレージタイプでのコストは以下のため、月額252USDの削減が期待できます。

ストレージタイプによるコスト比較

ポイント

ストレージタイプを最適化することで、コストを大幅に削減できます。特に、I/O性能が必要ない場合は、汎用SSD(gp2)を利用するとよいです。


3. リザーブドインスタンスの活用

アプローチ

オンデマンド料金が高く、長期的にRDSを使用することが分かっている場合、リザーブドインスタンスを購入することで、コストを大幅に削減できます。
リザーブドインスタンスは1年または3年のコミットメントを前提に割引が適用されるため、オンデマンドインスタンスに比べて最大で40%のコスト削減が期待できます。

db.t3.mediumの場合、リザーブドインスタンスの活用有無でのコストは以下です。リザードインスタンス1年利用だけでも、月額34USD程度のコスト削減が期待できます。

リザードインスタンス活用有無による価格表

ポイント

長期的な利用が予想されるRDSインスタンスに対しては、リザーブドインスタンスを活用することで、コストの削減が可能です。
オンデマンド料金と比較して、割引率が高いため、特に3年契約を検討する価値があります。


4. 自動バックアップとスナップショットの最適化

アプローチ

自動バックアップやスナップショットは、定期的に実行されますが、不要なバックアップやスナップショットを削除することで、ストレージコストを削減しました。
バックアップの保持期間を短縮することや、不要なスナップショットを定期的に削除する運用を導入しました

コスト計算

バックアップストレージ: 0.095USD/GB/月
50GBの不要なスナップショットを削除する場合: 50GB × 0.095USD = 月額4.75USDの削減


結果

これらの最適化アプローチにより、RDSのコストを全体で約50%削減することができました。
特に、インスタンスサイズの見直しとストレージタイプの最適化が大きな影響を与え、リザーブドインスタンスの活用で長期的なコスト削減効果をさらに高めました。


総合的なコスト削減効果(月額)

  • インスタンスサイズの適正化による削減: 200USD

  • ストレージタイプの最適化による削減: 252USD

  • リザーブドインスタンスの活用による削減: 34USD

  • バックアップとスナップショットの最適化による削減: 4.75USD

  • 合計削減額: 490.75USD


Amazon RDSのコスト削減は、インスタンスの見直しやストレージの最適化、長期的な利用を考慮したリザーブドインスタンスの活用など、いくつかの簡単な手順で達成可能です。




X(旧Twitter)・Facebookで定期的に情報発信しています!

はじめに

AWSのアカウント管理を実施するにあたり「Well-Architected Framework」への考慮は必要不可欠です! 私たちAWSユーザは、AWS Organizationsを利用したマルチアカウント戦略の実践を、AWSからベストプラクティスとして推奨されています。 今回は、AWS Organizationsを利用したマルチアカウント戦略の実践により、AWSアカウント管理でよくある課題を解決する方法をいくつかご紹介いたします。


目次

  • AWSアカウント管理でよくある課題
  • AWS Organizationsによるマルチアカウント戦略
    • AWS Organizationsのみで実現
    • AWS Organizations + AWSマネージドサービスの組み合わせで実現
  • まとめ


AWSアカウント管理でよくある課題

まずはじめに、


  • アカウント管理
  • セキュリティ
  • コスト


の3つの観点から、AWSアカウントを利用する上でお客様からよく伺う課題を見ていきます。


観点 現状 課題
アカウント管理 ・複数のシステム管理に伴いAWSアカウント数が(開発/検証/本番を含めると)20〜30個ある
・AWSアカウントは社内担当者もしくは社外ベンダーが管理している
・開発会社は複数に渡り、運用もベンダーに一任している
・AWSアカウント数が多く管理できていない
・アクセス権が細かく適切に付与できていない
・設定内容がセキュリティ要件を満たしているのかをチェックする機能が無い
・チェックする機能はあるがコストがかかっている
セキュリティ ・導入必須なミドルウェアやツールの指定がある
・システム毎に個別の要件やルールがある
・ミドルウェアやツールの導入率が低い
・上記未導入時の検知 → 改善・運用が構築されていない
・個別の要件やルールの適用確認が困難である
・不正アクセス等の検知ができていない
コスト ・AWSアカウント毎に請求が個別である
・AWSのコストは月1度の請求で確認している
・個々の請求処理が手間である
・AWSの急激なコスト上昇を把握できていない
・不要なリソースの放置による微細なコスト上昇に気付いていない
・AWSの予算オーバーを請求段階でしか検知できていない


これらの課題の多くは、AWSアカウントの 個別管理 に起因しています。 では、上記課題の解決策を、AWS Organizationsを利用したマルチアカウント戦略の観点から確認したいと思います。


AWS Organizationsによるマルチアカウント戦略

まずは、AWS Organizationsの機能について確認します。


AWS Organizationsとは、AWSアカウントを統合・管理・制御するためのAWSサービスであり、追加料金は不要です。1つのAWSアカウントを管理アカウントとして指定することで組織を作成します。その組織へのAWSアカウントの作成または追加により、階層構造を実現します。この階層構造により、システムやプロジェクト毎にAWSアカウントを分けて管理することが可能です。これが、AWS Organizationsを利用したマルチアカウント戦略です。さらには、AWS OrganizationsとAWSマネージドサービスを組み合わせることにより、一層ハイレベルなAWSアカウントの管理を実現します。


pasted-2024.08.08-14.22.30.png


以下では、AWS Organizationsを利用した具体的な課題の解決方法を見ていきます。


AWS Organizationsのみで実現


観点 課題 解決方法
アカウント管理 ・AWSアカウント数が多く管理できていない
・アクセス権が細かく適切に付与できていない
・OU(Organization Unit)単位でAWSアカウントをグループ化する
・AWS Organizationsに対応しているAWSサービスに対してOU単位で設定を実施する
・IAMグループごとにアクセス可能なAWSアカウントやAWSリソースへの権限の範囲を指定する
セキュリティ ※AWS Organizations + AWSマネージドサービスの組み合わせで実現
コスト ・個々の請求処理が手間である ・管理アカウントにて全てのAWSアカウントのコストを一括支払いする


AWS Organizations + AWSマネージドサービスの組み合わせで実現


観点 課題 解決方法
アカウント管理 ・設定内容がセキュリティ要件を満たしているのかをチェックする機能が無い
・チェックする機能はあるがコストがかかっている
・AWS Configを組み合わせることで複数のAWSアカウントのAWS Configデータを管理アカウントに一元的に集約し、AWSリソースの設定と関係を継続的に監査・評価する
セキュリティ ・ミドルウェアやツールの導入率が低い
・上記未導入時の検知 → 改善・運用が構築されていない
・個別の要件やルールの適用確認が困難である
・不正アクセス等の検知ができていない
・AWS Systems Managerを組み合わせることで各AWSアカウントのインスタンスに対してセキュリティパッチを一元適用する
・Amazon S3を組み合わせることで各AWSアカウントのセキュリティログを一元的に集約する
・Amazon Athenaを組み合わせることで集約されたセキュリティログに対してクエリを一括に実行し、セキュリティインシデントの兆候を漏れ無く分析する
コスト ・AWSの急激なコスト上昇を把握できていない
・不要なリソースの放置による微細なコスト上昇に気付いていない
・AWSの予算オーバーを請求段階でしか検知できていない
・AWS Cost Anomaly Detectionを組み合わせることで各AWSアカウントの急激なコスト上昇を一元的にキャッチする
・AWS Budgetsを組み合わせることで予算逸脱時に通知を受け取る


このようにAWS Organizationsにおけるマルチアカウント戦略を最大限活用することで、


  • アカウント一元管理 : 複数AWSアカウントの統合管理
  • セキュリティ強化 : 漏れのない完全なるセキュリティポリシー
  • コスト追跡 : AWS組織全体でのコスト最適化


これらを実現し、AWSアカウントを管理する上での多くの課題を網羅的に解決することができます!


まとめ

ここまで「AWS Organizationsによるマルチアカウント戦略」について見てきました。 ご自身が利用されているAWSアカウントの管理状況と比較していただき、改善点など見つかりましたでしょうか? AWS Organizationsやその他のAWSマネージドサービスとの組み合わせを採用し、AWSのベストプラクティスに沿ったAWSアカウント管理を実践しましょう!ご精読いただきありがとうございます。

はじめに

今回は、アクセルユニバースのインフラエンジニアがAWSアカウントのコスト削減を実施する際に利用しているチェックリストをご紹介いたします。


AWSコスト削減チェックリスト

私たちアクセルユニバースのAWSコスト削減チェックリストは


  • チェック対象リソース/サービス
  • コスト削減観点(状態)
  • 手段


の3つの項目から構成されています。 私たちインフラエンジニアはこのチェックリストを元に「クラウド支出の最適化(FinOps)」におけるコストの最適化を実践しております。


No. チェック対象 コスト削減観点(状態) 手段
1 Amazon S3 不要な過去ログが溜まっていないか? ライフサイクルルールの設定
2 Amazon S3 アクセス頻度と保持期間を予測できていない or 考慮しておらず不適切なストレージクラスを選択してはいないか? Standard以外のストレージクラスの選択
3 リージョン 低レイテンシーよりもコスト最適化を優先するか? 利用料が安いアメリカのリージョンの選択
4 インスタンス 開発環境等の常時稼働不要なサーバはないか? 夜間・土日の停止設定・時間帯ベースのスケーリングを活用
5 Amazon EC2 既にFargateが常時稼働しているにも拘らず改めてバッション用のEC2を構築してはいないか? バッションとしてのFargateの利用・EC2インスタンスの停止
※ただし操作ミスなどへの考慮が必要
6 Amazon EC2 本番環境等の常時稼働必須なサーバはあるか? Reserved InstancesやSavings Plansの予約購入
7 Amazon RDS 本番環境等の常時稼働必須なサーバはあるか? Reserved Instancesの予約購入
8 Amazon ElastiCache 本番環境等の常時稼働必須なサーバはあるか? リザーブドノードの予約購入
9 AMI 最新以外のスナップショットも保存されてはいないか? 検討後不要とされたスナップショットの削除
10 Amazon EBS ボリュームタイプに過不足はないか? ボリュームタイプの見直し
11 Amazon VPC どのリソースとも紐づけられていないIPアドレスを固定しては
いないか?
不要なElastic IPアドレスの解放
12 Amazon CloudFront 年間を通して「これ以上は常に使っている」という使用量の
最低ラインが把握できているか?
CloudFront Security Savings Bundleの利用
13 Amazon CloudWatch 吐き出されたログが溜まりっぱなしではないか? CloudWatch Logsへの保持期間設定
※非機能要件への考慮が必要
14 AWS Lambda 必要以上にコンピューティングリソースを構築していないか? トリガーやイベント発生検知の設定
15 NAT Gateway 意味もなくNAT Gatewayを通してはいないか? 代替手段としてのVPCエンドポイントの利用
16 AWS Config 記録の不要なリソースはあるか? 記録対象外リソースとしての指定
17 AWS Systems Manager Resource Scheduler Systems ManagerにてEC2インスタンスの管理をしているか? EC2インスタンスへのスケジュールの指定
18 AWS Cost Optimization Hub コスト削減に対する対応が不適切ではないか? コスト最適化に関する適切な戦略の特定・推奨


こんなお悩みはありませんか?

  • クラウド化は実施したが想定よりコストがかかっている...
  • コスト削減可能性を感じているが多忙で調査に手が回らない...


そのお悩みアクセルユニバースが解決します!

アクセルユニバースでは、素早くお手頃、でも根本的にAWSコストの最適化を実現します。 AWSコスト削減サービスをお求めの方はこちらまで

はじめに

AWSにてデプロイのリスクを緩和するにあたり「Well-Architected Framework 運用上の優秀性」への考慮は大変重要です。 今回は、AWS Summit Japan「Amazon ECSから考える安全なアプリケーションデリバリー」をベースに、デプロイのリスクを緩和する方法をご紹介いたします。


目次

  • 安全なアプリケーションデリバリーとは
  • 線形デプロイ/Canaryデプロイ
  • 機能フラグ(Feature Flag)
  • 自動ロールバックの必要性
  • まとめ


安全なアプリケーションデリバリーとは

AWSの定義する「安全なアプリケーションデリバリー」とは意図しない障害が発生した際の影響範囲を最小限にすることです。 残念ながら、システムを運用する上で、意図しない障害が発生する可能性をゼロにすることはできません。 だからこそ「いかに影響範囲を最小限にするか?!」に着目すべきなのだと思います。


いかに影響範囲を最小限にするか?

AWSはこの課題を解決するためにデリバリーによる新機能の公開を少数のユーザから段階的に行う手法を推奨しています。


新機能を段階的に公開する手法

  1. 線形デプロイ/Canaryデプロイ
  2. 機能フラグ(Feature Flag)


それでは、それぞれの手法を詳しく見ていきたいと思います。


1. 線形デプロイ/Canaryデプロイ

線形デプロイおよびCanaryデプロイとは、ユーザからのトラフィックの一部分のみを新バージョンのアプリケーションへアクセス許可する手法です。

pasted-2024.07.09-18.01.06.png


線形とCanaryの違い

線形デプロイ
線形デプロイとは、デリバリーされた新機能にアクセス許可するトラフィックの比率を10% → 20% → 30%...と線形的に増やし、正常性確認を慎重に行う手法です。

Canaryデプロイ
Canaryデプロイとは、デリバリーされた新機能にアクセス許可するトラフィックの比率を10%程度の少数に定め、その小規模なトラフィックに対して正常性が確認でき次第、全てのトラフィックを新機能にアクセス許可する慎重かつ大胆な手法です。


線形/CanaryデプロイのAmazon ECSでの実践

それでは、線形デプロイ/CanaryデプロイのAmazon ECSでの実践について詳しく見ていきたいと思います。


必要となるAWSのリソース

  • AWS ALB
    → ユーザからのトラフィックの一部を新バージョンのアプリケーションにルーティングさせる役割
  • Amazon ECS
    → 現バージョンで稼働させているアプリケーションはそのまま稼働させつつ新バージョンのアプリケーションも追加で稼働させる役割
  • AWS CodeDeploy
    → 線形デプロイ/Canaryデプロイの司令塔
    → AWS ALBにおけるトラフィックの比率管理およびAmazon ECSにおけるサーバの並行稼働を実現する役割

pasted-2024.07.09-18.03.16.png


フロー

  1. 新バージョンのアプリケーションをデプロイ
    → AWS CodeDeployがAmazon ECSに自動でデプロイ
  2. ユーザからのトラフィックの一部を新バージョンのアプリケーションにルーティング
    → AWS CodeDeployがAWS ALBのトラフィックの比率を自動で変更
  3. 全てのユーザからのトラフィックを新バージョンのアプリケーションにルーティング
    → AWS CodeDeployがAWS ALBのトラフィックの比率を自動で変更
  4. 現バージョンのアプリケーションを停止
    → AWS CodeDeployがAmazon ECSを自動で停止


上記のようなフローで、線形デプロイ/CanaryデプロイをAmazon ECSにて実践することができます。


ALBの仕組み

AWS ALBはターゲットグループと重み(トラフィックの比率)を設定することができます。
例えば、現バージョンのターゲットグループに80%の重みを、新バージョンのターゲットグループに20%の重みを設定します。 そうすることで、ユーザからのトラフィックの一部分のみを新バージョンのアプリケーションへアクセス許可することが可能です。 しかしながら、その設定だけではユーザの割り当て先が毎回バラバラになってしまう課題が残ります。
そこで登場するのが、AWS ALBの機能の内の1つであるスティッキーセッションです。


スティッキーセッション
セッションが有効な間、クライアントとサーバーを常に一対一で接続させる役割


スティッキーセッションを利用することで、ユーザの割り当て先を固定し、線形/CanaryデプロイのAmazon ECSでの実践を可能にします。


2. 機能フラグ(Feature Flag)

機能フラグ(Feature Flag)とは、特定の属性を持つユーザからのトラフィックのみに対して新バージョンのアプリケーションへアクセス許可する手法です。 具体的には、アプリケーションコードに「機能フラグがONの場合にのみ実行されるロジック」を組み込み、機能フラグのON/OFFによりアプリケーションの振る舞いを切り替えます。


補足 : フラグ(Flag)とは、ONかOFFのどちらの状態かを判断するために使用する変数です。


アプリケーションコードに組み込むロジック

987178efe999f29749c640823355fdac838ceaef.png

ユーザからのトラフィックの情報に含まれるuserID(Flag)が、機能フラグ(FlagGroup)に含まれている場合にのみ、新機能へのルーティングがONになります。 これにより、ユーザID単位での新機能へのON/OFFを制御することが可能になります。


機能フラグ(Feature Flag)のAmazon ECSでの実践

それでは、機能フラグ(Feature Flag)のAmazon ECSでの実践について詳しく見ていきたいと思います。


必要となるAWSのリソース

  • AWS AppConfig
    → 機能フラグを管理する役割
    → アプリケーションコードに組み込むロジックの保存や配布を簡素化する役割
  • Amazon ECS
    → 機能フラグを定期的に取得するためのサイドカーコンテナ(AppConfigエージェント)を稼働させる役割
  • AppConfigエージェント(サイドカーコンテナ)
    → アプリケーションの代わりに機能フラグを定期的に取得する役割
    → アプリケーションが直接的にAWS AppConfigを叩く必要がなくなり、アプリケーションコードをよりシンプルに書くことが可能

pasted-2024.07.09-18.05.02.png


フロー

  1. 新機能を含むアプリケーションコードを本番環境にデプロイ
    → AWS AppConfigに保存されている機能フラグはOFFの状態
  2. 新機能を公開したい一部のユーザに対して機能フラグをONに変更
    → AWS AppConfigに保存されている機能フラグの値を更新
  3. 機能フラグがアプリケーションに反映され一部のユーザに新機能が公開
    → AppConfigエージェント(サイドカーコンテナ)が非同期で機能フラグの値を取得しアプリケーションに反映
  4. 全てのユーザに対して機能フラグをONに変更し、全体のユーザに新機能が公開


上記のようなフローで、機能フラグをAmazon ECSにて実践することができます。


自動ロールバックの必要性

ここまで、線形/Canaryデプロイと機能フラグについて見てきましたが、ここで自動ロールバックについて考えます。 線形/Canaryデプロイや機能フラグによる新機能の段階的公開では、問題が確認されたタイミングでロールバックを実施する必要があります。 もし、ロールバック作業が手動である場合、せっかく確保できた時間リソースを無駄にしてしまうことになります。


そこで登場するのが自動ロールバックです。


自動ロールバックのAmazon ECSでの実践

それでは、自動ロールバックのAmazon ECSでの実践について見ていきたいと思います。


必要となるAWSのリソース

  • Amazon CloudWatch
    → AWS CodeDeployとAWS AppConfigと連携しALARM状態を伝達する役割
  • Amazon ECS
    → 新バージョンのアプリケーションからメトリクスを発行する役割
  • AWS CodeDeploy & AWS AppConfig
    → AWS CloudWatchのALARM状態時に自動でロールバックをする役割

pasted-2024.07.09-18.07.09.png

フロー

  1. 常時発行されるメトリクスに対してしきい値を設定
    → Amazon ECSから常時発行されるメトリクスに対してAmazon CloudWatchアラームを作成
  2. しきい値を超えた場合のみ旧アプリケーションへの自動ロールバックを実行
    → AWS CodeDeploy & AWS AppConfigがAmazon CloudWatchのALARM状態を検知し自動ロールバックを実行


補足 : Amazon CloudWatchのデフォルト機能だけでは自動ロールバックをすることはできません。そのため、上記のようなアラームの作成が必要とされます。


上記のようなフローで、自動ロールバックをAmazon ECSにて実践することができます。


まとめ

ここまで「Amazon ECSから考える安全なアプリケーションデリバリー」について見てきました。 デプロイのリスクを緩和する方法のイメージは湧きましたでしょうか?


AWS CodeDeployやAWS App Configなど、マネージドなリソースを利用することで時間リソースを確保するだけではなく、オペレーションミスなどによるインシデントを未然に防ぐことができます。 AWSにおいて、アプリケーションのデリバリー頻度を上げつつ、そのデリバリーを安全に行いたい想いを持つエンジニアの方々には、ぜひ利用を試みていただきたいです! ご精読いただき、ありがとうございました。

はじめに

AWSのコスト管理を実施するにあたり「Well-Architected Framework コスト最適化の柱」への考慮は欠かせません! その中でも「クラウド財務管理(CFM)」の実装は特に重要です! 今回は、そのクラウド財務管理(CFM)を実践するためにクリアすべきミッションを3つご紹介いたします。


目次

  • クラウド財務管理(CFM)とは?
  • ミッション① : コストの可視化
  • ミッション② : コストの最適化
  • ミッション③ : コストの計画・予測の確立
  • まとめ


クラウド財務管理(CFM)とは?

まず初めに、クラウド財務管理(CFM)を一緒に確認しましょう。 クラウド財務管理(CFM)は、AWSにおいて「クラウド支出の最適化(FinOps)」=コスト管理を実践するための指標となり、


  • 可視化
  • 最適化
  • 計画・予測の確立


の3つの項目から構成されています。 私たちAWSユーザは、クラウド支出の最適化(FinOps)の継続的な実践を、AWSからベストプラクティスとして推奨されています。 それでは、3つの項目をそれぞれミッションとし、適切な対応を1つずつ確認していきたいと思います。


ミッション① : コストの可視化

pasted-2024.08.14-12.43.06.jpg

ミッション①は「コストの可視化」です。 実際にAWSのコスト管理を実施するためには、その第1段階として、AWSアカウントのコストの現状を把握しなければなりません。 とはいえ、コストの可視化を実践するためには、どのAWSサービスを採用するべきでしょうか?


AWSでは、コストの可視化のために下記のサービスを採用することを推奨しています。


  • AWS Cost Explorer
    • AWSコストのグラフ化によりコストの可視化が可能
    • → レポートパラメータの使用による粒度別のコストデータ調査
    • → 過去のコストデータの使用による向こう1年のコスト視覚化


  • コスト分配タグ
    • AWSリソースへのタグ付けによりコストの追跡・可視化が可能
    • → キーと値の組み合わせによるコスト分類
      • 例) キー : env
      • 例) 値 : prod
      • 注意点 : 各アカウントでのAWSリソースへのタグ付けだけでは不十分であり、ペイヤーアカウントでのコスト配分タグへの登録が必須
    • AWS Tag Editor
      • コスト分配タグを付け忘れたAWSリソースの検索およびタグの付与が可能
      • → コスト分配タグの漏れの無い付与による徹底的なコスト管理


  • AWS Cost and Usage Report(CUR) 2.0
    • AWSコストの テーブル化 によりコストの可視化が可能
    • → AWS Cost and Usage Report(CUR) 2.0の S3 への格納により Amazon Athena のSQLを使用したコストデータ分析が可能
    • 特徴 : AWS Cost Explorerよりも詳細にコストの可視化・分析が可能


  • AWS Cost and Usage Dashboard(CUD)
    • AWSコストデータの ダッシュボード への一元的な表示によりコストの可視化が可能
    • → AWS Cost and Usage Dashboard(CUD)の S3 への格納により Amazon QuickSight のSQLを使用したコストデータ分析が可能
    • 特徴 : ダッシュボードの作成によるハイクオリティな可視化が可能


基本的には、AWS Cost Explorerやコスト分配タグにてコストの可視化を実践することができます。 しかしながら、本格的なコストの可視化を実践するためには、AWS CUR 2.0やAWS CUDの採用が推奨されます。 どのサービスを利用するかにより可視化のレベルが異なるため、環境や非機能要件に合わせて手段を適切に採用しましょう!


ミッション② : コストの最適化

pasted-2024.08.14-12.49.09.jpg

ミッション②は「コストの最適化」です。 AWSのコスト管理の第2段階として、実際にAWSアカウントのコストの削減を実践していきましょう。


コストの最適化はAWSから推奨される手順があり、


  1. 需要に応じたスケジューリング
  2. 適切なインスタンスタイプ・ストレージの見直し
  3. 1と2を踏まえたReserved InstancesまたはSavings Plansの購入


の3つの項目から構成されています。 それでは、手順を3つのブロックに分けて確認していきます。


1. 需要に応じたスケジューリング

需要に応じたスケジューリングとは、例えば、開発環境などにおける常時稼働不要なサーバの夜間・土日の停止などを指します。 AWSでは、需要に応じたスケジューリングのために下記のサービスを採用することを推奨しています。


  • Amazon EventBridge スケジューラ
    • タスクへのスケジュールの指定によりAWSコストの最適化が可能
    • → cron式やrate式の使用によるタスク別の詳細な時間管理


  • AWS Lambda
    • 必要な時間帯のみの関数の実行によりAWSコストの最適化が可能
    • → トリガーとの同期により関数を実行
    • → イベントの発生の検知により非同期で関数を実行


  • AWS Systems Manager Resource Scheduler
    • AWS System ManagerにてEC2インスタンスの管理をしている場合、EC2インスタンスへのスケジュールの指定によりAWSコストの最適化が可能
    • → Quick Setupでの設定によりEC2インスタンスの起動と停止を自動で実行


  • Amazon EC2 Auto Scaling
    • Amazon EC2インスタンスへのスケジュールの指定によりAWSコストの最適化が可能
    • → スケジュールされたアクションの作成により特定の時間帯に希望する分のキャパシティが増減


2. 適切なインスタンスタイプ・ストレージの見直し

AWSは、適切なインスタンスタイプ・ストレージの見直しに応じる適切な対応についてAWS Cost Optimization Hubにて確認することを推奨しています。


  • AWS Cost Optimization Hub
    • AWSアカウントへの推奨アクション(レコメンデーション)の一元化によりAWSコストの最適化に関する適切な戦略の特定が可能
    • → 各アカウントにおけるアイドル状態のAWSリソースの検出
    • → 各AWSリソースの適切なサイズやスペックの推奨


3. 1と2を踏まえたReserved InstancesまたはSavings Plansの購入

AWSは、さらなるコストの最適化を目指してReserved InstancesまたはSavings Plansを購入することを推奨しています。


  • Reserved Instances(RI)
    • 一定期間(1年or3年)の継続利用をコミットすることにより大幅な割引(最大-72%)が適用可能
    • SPとの違い
      • → 事前にインスタンスのタイプの指定が必要
        • リージョン/インスタンスファミリー/テナンシー/OS/アベイラビリティーゾーン


  • Savings Plans(SP)
    • Reserved Instancesの後に発表された費用見積ツールであり、仕様はリザーブドインスタンスとほぼ同様だが高い柔軟性を持つ
    • 一定期間(1年or3年)一定量の継続利用をコミットすることにより大幅な割引(最大-72%)が適用可能
    • RIとの違い
      • → 事前に対象サービスに対する1時間当たりに支払う利用金額の決定が必要


AWSアカウントにおいて既に採用しているサービスやリソースにより、スケジューリングの手段、見直しの箇所、および料金モデルが異なります。 ご自身のAWSアカウントの環境に最もマッチするサービスを見極めた上で、コストの最適化を適切に実践しましょう!


ミッション③ : コストの計画・予測の確立

pasted-2024.08.14-12.58.17.jpg

ミッション③は「コストの計画・予測の確立」です。 AWSのコスト管理を 継続的に 実施するために、その最終段階として、AWSアカウントのコストの計画・予測を確立しなければなりません。 AWSでは、コストの計画・予測を確立するために下記のサービスを採用することを推奨しています。


  • AWS Budgets
    • AWSコストのカスタム予算の追跡によりコストの計画・予測の確立が可能
    • → カスタム予算におけるしきい値の設定による予算超過時のアラート発信
    • → 予算超過時アラートによるカスタムアクションの自動的な実行


  • AWS Cost Anomaly Detection
    • 機械学習を通じたAWSコスト異常検出と根本原因分析によりコストの計画・予測の確立が可能
    • → AWSコストのカスタム異常しきい値の設定によるベースライン逸脱時のアラート発信
    • → 高度な機械学習によるベースライン逸脱時アラートの根本原因分析


しきい値の逸脱時にアラート通知が可能なサービスを適切に実装することにより、あらかじめ定めた予算やコストの大幅なズレを未然に防ぎ、コストの計画・予測を確立しましょう!


まとめ

ここまで、クラウド財務管理(CFM)を実践するためにクリアすべき3つのミッションを順に見てきました。 ご自身のAWSアカウントのコスト管理を実施するための最適なサービスは見つかりましたでしょうか?


  • ミッション① : コストの可視化
  • ミッション② : コストの最適化
  • ミッション③ : コストの計画・予測の確立


上記の3つのミッションを継続的に実践することで、クラウド財務管理(CFM)の実装を叶え、AWSのベストプラクティスに沿ったコスト管理を徹底しましょう! ご精読いただき、ありがとうございました。

データ分析基盤構築とは、大量のデータを蓄積・変換・分析するためのインフラを開発することです。主軸となるデータレイク・データウェアハウス・BIツールの他、NoSQLデータベース、データパイプラインツール、ETLツールなど様々な要素があり、それぞれ様々なベンダーから多種多様な製品が出ています。

比較項目は膨大で、複雑です。性能・機能・セキュリティ・コスト......一体何を基準に選べばよいのでしょうか。当社には一つの戦略があります。それは、

" 分析ツールはコスト最適性で、データ基盤は運用性で選ぶ。 "


これがデータ利活用を成功させるための鍵です。以下のように、2つのポイントに分けられます。

データ分析基盤の構成.jpg

詳しく解説していきます。

秘訣①BIツールの二極化と、「コスト最適」な配分

まずは実際に、分析ツールの費用をご紹介しましょう。データ利活用の最初に導入するデータ分析ツールとしては、BIツールが一般的です。TableauとQuickSightという2つのBIツールを比較します。1,000人の従業員が利用する場合、支払額は次のようになります。

[ケース1]

  • Tableau:約3,000万円/年
  • QuickSight:約800万円/年


3〜4倍の差です。

極端な例ではありません。BIツールの価格は二極化しており、このくらい高いか、安いか、どちらかです。最初に適切な製品を導入できないと、その後毎年不必要なコストがかかり続けてしまいます。

とはいえ高価なツールには、独自の機能や、高度な利用をする際の使いやすさがあります。例えばTableauはドラッグ&ドロップのような直感的な操作によって、簡単・迅速にデータ分析ができ、分析を主務とするユーザーに向いています。ただ一律に安価なものを導入すると、結局機能が不足してデータ利活用が進まないという本末転倒の事態になるでしょう。

「安ければいい」でも「高機能であればいい」でもなく、「必要な利用者にだけ必要な機能を」。それが「コスト最適化」の観点です。具体的には、

  • 自社のニーズを洗い出し、
  • 「誰が・どんなタスクを・どの程度」できる必要があるかを見極め、
  • それぞれに必要十分なツールを用意すること。


これによってコスト最適な利活用推進を図ることが重要なのです。

ツール配分の例を考えましょう。先ほどの従業員1,000人のうち、データからインサイトを得るための分析業務を行うのは経営戦略部と店舗開発部の計100人で、その他の900人はあらかじめ作成された可視化ダッシュボードを日々の業務で参照するだけだとします。分析を行う100人(とツールを管理するエンジニアチーム)がTableauを利用し、残りの900人はQuickSightを利用するのが適切です。費用は以下の通りです。

[ケース2]

  • Tableau:約700万円/年
  • QuickSight:約800万円/年
  • 合計:約1,500万円/年


さらに、従業員に対する細かいアクセス権限の設定などが不必要である場合、QuickSightの代わりに無料の Looker Studio を利用できます。この場合、費用はさらに安くなります。

[ケース3]

  • Tableau:約700万円/年
  • Looker Studio:0円/年
  • 合計:約700万円/年


これはあくまで簡単な例ですが、「分析か/可視化か」「細かいアクセス権限管理が必要か/不要か」という観点は一般的なものです。自社のニーズをこのような形で整理し、それに合った適切なツールを選んでいくというイメージをつけましょう。

では具体的に、どのようなツールがあるのでしょうか。高価・高機能なものでは、Board、Domo、Qlikといった有名製品にそれぞれ特長がありますが、AIによる自然言語処理で直感的に使えるThoughtSpotのような製品も生産性を向上し、使い始めのハードルを下げるでしょう。安価なものはGoogleの Looker Studio が代表的ですが、OSSのMetabaseも、自動でダッシュボードを生成してくれるX-rayという機能に魅力があります。

秘訣②利活用に必要な「運用性の高いデータ基盤」

「データ基盤」とは、データを利用可能な形で蓄積するためのインフラストラクチャのことです。と一口に言っても、実際にはデータパイプライン・データレイク・ETL・データウェアハウスと、多くの構成要素があります。それぞれの構成要素を動かすのに必要なプログラムや設定の項目は非常に多く、開発や運用の工数が大きくなります。分析ツールが費用の勘所であるのに対して、データ基盤はいわば工数の勘所です。

しかし本当に工数を割くべきなのは、開発や運用ではありません。要件定義とそれに基づく継続的デリバリーに力を入れてこそ、将来の成功があります。データ基盤の構築はDXやクラウド移行と似ており、現行のシステムや業務自体の変化を伴うものです。様々なステークホルダーへの説明・ヒアリング・調整が不足していれば、プロジェクトは失敗へ向かいます。一方で、プロジェクトのエンジニアチームが主体となって調整を行い、使う人たちにとって使いやすいデータ基盤を構築することができれば、利活用は順調な滑り出しを迎えられます。データ基盤は一度出来上がった後でも現場から様々な要望が舞い込んできますが、それに応じられるコミュニケーション体制も確立できるはずです。

そのため、エンジニアチームがコミュニケーションに時間を割けるように、データ基盤では保守運用性の高い構成を選択し、開発工数も抑えることが重要になります。

その視点で一般的に優れているのは、基盤をAWSサービスだけで構築することです。AWSでは、データウェアハウスのメンテナンス自動化、アクセス権限やメタデータの管理一本化などの恩恵を得られます。また、AWS上に構築されることの多い対向業務システムとの連携もスムーズです。

もちろん、どのような場合でもAWSがベストな訳ではありません。Google Cloudは先進的な性能によって、データ基盤市場に確固たる地位を築いています。データウェアハウスについては、独自の機能と料金システムで支持を伸ばしているSnowflakeも検討の余地があります。

データ利活用のスタートダッシュ

"分析ツールはコスト最適性で、データ基盤は運用性で選ぶ。"というテーマについて解説してきました。それでは、なぜこれが望ましい戦略なのでしょうか。それは、「データ利活用/データドリブン経営を、最低限のコストで、スムーズに始められる」からです。このうち「最低限のコスト」については、分析ツールを適切に選ぶことで高すぎる負担を避けられるということが、まずあります。運用性の高いデータ基盤も、保守・改修を含めたTCOを抑えることで、コストカットに繋がります。

では、「スムーズに始められる」とはどういうことでしょうか。データ利活用/データドリブン経営の「スムーズな開始」を阻む要因は、主に2つ考えられます。1つ目は「利用者のリテラシー不足」で、「ツールの操作がわからない」「データが何に使えるのかわからない」といったものです。2つ目は「エンジニアの設計ミス」で、「ツールのスペックが足りない」「使い物にならないデータを生成している」などです。この2種類の失敗は、「基盤を使う人たちとエンジニアチームのコミュニケーション不足」という1つの失敗から出てくる結果に過ぎません。

基盤構築の段階から、エンジニアチームが積極的に利用者に関わっていくことが重要なのです。コミュニケーションを重ねることで、利用者がデータを理解していくことができます。エンジニアチームの側も、フィードバックから要件定義、製品選定やスキーマ設計のヒントを与えられます。

「コスト最適に・スムーズに始める」ことにゴールを置いて基盤構築をすれば、その後のデータカルチャーの浸透、データによる収益拡大といった経営目標へと繋がっていくでしょう。そのためには、分析ツールはコスト最適性で、データ基盤は運用性で選ぶことになります。

最適な製品選定と要件調整のご提供

アクセルユニバース株式会社では、当社の掲げる「顧客中心主義」に基づいて、お客様に合わせた最適な分析ツール・データ基盤を立案・開発いたします。お客様の状況をヒアリングし、適切なプランをご提案することを得意とする企業です。

また、必要に応じて、お客様部署間のファシリテーションなどの総合的なITコンサルティングを提供しております。

まずは追加でお聞きになりたい情報から、お気軽にご相談ください。

(お問い合わせはこちら)

BIツールの費用計算

いずれも記事公開時点での情報です。1ドル=150円、有効数字1桁としました。 Tableau公式の価格情報AWS公式の料金情報 をもとに計算しています。

[ケース1] Tableau:「Tableau Creator」10人、「Tableau Explorer」100人、「Tableau Viewer」890人。 QuickSight:「管理者」10人、「作成者」100人、「閲覧者」890人。

[ケース2] Tableau:「Tableau Creator」10人、「Tableau Explorer」100人。 QuickSight:「管理者」10人、「作成者」100人、「閲覧者」790人。

[ケース3] Tableau:「Tableau Creator」10人、「Tableau Explorer」100人。 Looker Studio:無料ユーザーのみ。

ご挨拶

AWS全冠エンジニアの小澤です。
今年の目標はテニスで初中級の草トーナメントに優勝することです。よろしくお願いいたします。

本記事の目的

本記事では、生成AIでVOC分析を行うことで得られた知見を共有したいと思います。

昨今、生成AIの登場など機械学習の進歩は目覚ましいものがあります。一方、足元では自社データの利活用が進まず、世の中のトレンドと乖離していくことに課題感を持たれている方も多いかと思います。また、ガートナーの調査(2024年1月)によると、日本企業でデータ活用の成果を得られている企業は3%にとどまっているようです。

特に顧客の声(Voice Of Customer)は、大量の非構造化データで、内容も多様かつ複雑なため特に分析が難しい領域です。また、効果的に分析できれば実りの大きい領域でもあります。

早速やってみた

VOC分析のデモ対象としてCSVファイルを用意しました。こちらは「都内に展開する高級ハンバーガーチェーンのカスタマーフォームのデータ」という設定で、生成AIで顧客の声を99件作成しています。

上記のCSVファイルを生成AIで前処理して、BIツールに取り込むことで下記デモのように手軽にVOC分析が始められます。


今回のやってみたで得られたポイントは以下の3点です。

  • テキストマイニングの専門的知見がなくても大量データを分析してインサイトを創出できる
  • GPT-4で一つの顧客の声から複数のカテゴリと感情分析を抽出できる (GPT-3.5だと物足りない)
  • どのようにカテゴリを組成するかが分析の肝であり、その目的に応じてカテゴリの再構築が必要


それでは、具体的な手順に入っていきます。

1.データの前処理

デモデータに含まれるお客様申し出内容を生成AIでカテゴライズ、感情分析、要約します。
今回はカテゴリ一覧も生成AIで用意させました。最終的に利用したカテゴライズ用プロンプトは記事の最後に参考情報として記載しています。

当初、前処理にはGPT-3.5を利用しましたが、カテゴライズの精度に少し物足りなさを感じたためGPT-4を利用するように変更しました。
GPT-4を利用して、一つの顧客の声から複数のカテゴリ、異なる感情分析を生成できたのは興味深い結果でした。人間だと一つカテゴライズしたら手を抜いてしまいがちとなるので、GPT-4と同程度の精度で大量のデータを以下のようにカテゴライズするのは難しいと思います。

INPUT

今日、プレミアムバーガー赤坂店でランチセットを利用しました。バーガーのサイズは満足できるものでしたが、サイドメニューのポテトが少なく感じました。
また、ドリンクの種類がもっと多ければ嬉しいです。価格に見合った量と質を期待していたので、少しガッカリしました。
しかし、店員さんの対応はとても良く、快適なランチタイムを過ごせました。今後、ランチセットの内容を見直し、コストパフォーマンスを高めることをお勧めします。

OUTPUT

[
  {
    "大カテゴリ": "店舗",
    "カテゴリ": "サービス",
    "サブカテゴリ": "スタッフの態度",
    "感情分析": "Positive",
    "要約": "店員の対応が良く、快適なランチタイムを提供"
  },
  {
    "大カテゴリ": "商品企画",
    "カテゴリ": "メニュー開発",
    "サブカテゴリ": "その他",
    "感情分析": "Negative",
    "要約": "サイドメニューの量とドリンクの種類に不満"
  },
  {
    "大カテゴリ": "商品企画",
    "カテゴリ": "フィードバック管理",
    "サブカテゴリ": "商品改善",
    "感情分析": "Neutral",
    "要約": "ランチセットの内容とコストパフォーマンスの改善を提案"
  }
]

それでは、これらの分析結果をBIツール(QuickSight)に取り込んで、どのようなインサイトが得られるか見ていきます。

2.全体把握

まずは円グラフとヒートマップで顧客の声をざっくり視覚化します。

スクリーンショット 2024-01-26 12.07.22.png

ヒートマップでは店舗のネガティブな声が目を引きますが、これは全体に占める「店舗」への声、ネガティブな声の割合を考慮すると自然な結果です。ここは更に細かく分析をしていく必要がありそうです。
一方で、「商品企画」への声はポジティブである比率が高く、商品力に優れたハンバーガーチェーン店であることが伺えます。

今回はエリアマネージャーになったつもりで店舗にフォーカスして分析を進めていきます。

3.店舗にフォーカスした分析

引き続き、店舗の声について全体把握するために円グラフとヒートマップでざっくり視覚化します。

スクリーンショット 2024-01-26 12.51.17.png

店舗へのネガティブな声の割合は、全体と比較すると少し高めであることが分かります。
ヒートマップを見ると、「待ち時間」や「スタッフの態度」に課題がありそうです。一方で、「雰囲気」はポジティブな声が多く、店舗の強みとなっていることが分かります

スクリーンショット 2024-01-26 13.03.08.png

店舗別のヒートマップを見ると、「プレミアムバーガー新宿」に多くのネガティブな声、「プレミアムバーガー赤坂」にポジティブな声が集まっていることが分かります。これらの情報を元に分析を深掘りしていきましょう

4.分析の深掘り

詳細分析はピボットテーブルを利用して行い、店舗横串で改善すべき項目を確認していきます。

スクリーンショット 2024-01-26 13.31.56.png

ここで、エリアマネージャーとしての私は店舗改善の指標として強みとなっている「雰囲気」に着目しました。
顧客からポジティブな評価を集めている赤坂店などはマネージャーとしての経験とも合致するところがあり、その要素を分析して他店舗に横展開する施策はイメージが湧きました。

一方で、クレーム件数の多い「待ち時間」はモバイルオーダーなどのシステム起因であったり、時間帯やプロモーションのピーク性など要因が絡まり合っており、クイックウィンが難しいことは自明だったので、今回はスコープから除外することにしました。

またVOC分析では「その他」を洗うことも重要です。ここには認知できていなかった課題が埋もれています。

スクリーンショット 2024-01-29 9.45.11.png

店舗改善で更にインサイトを得るためには、ユニフォームが「その他」に組み込まれないようカテゴリの再構築が必要でしょう。

やってみた振り返り

顧客の声という非構造化データをカテゴライズ・感情分析し、そこからインサイトを創出するデモをやってみました。

しかし、本当に価値があるのはインサイトから仮説を構築し、検証するための分析プロセスだと感じました。そのためには、カテゴリの再構築を繰り返すことで次々とインサイトを創出するインタラクティブな分析が必要です。
今回の例で言えば、店舗の雰囲気に「スタッフの態度」が大きく影響している可能性でないか?などの仮説が立ちますし、それに合わせてカテゴリの再構築が必要でしょう。

そして現場を分かっている人ほど、これらの顧客の声から精度の高い仮説を立てられると思います。また改善施策を実施後、適切に可視化されたダッシュボードでデータの時系列をトラックし、効果測定を行うことも重要です。

そのためにはデータ分析の専門性を持たなくても、担当者がインタラクティブにデータ分析と視覚化を行えるシステムが必要です。そのようなシステムは生成AIをデータ分析に組み込むことで、自然言語を介して実現出来ると思います。

AWSのマネージドサービス活用

AWSのマネージドサービスを組み合わせることで、VOC分析をセキュアにスモールスタートできます。

VOC分析構成図.drawio.png

Amazon Bedrockはエンタープライズ向けの生成AIでセキュアに利用できますし、QuickSight には自然言語でBIを構築する新機能も発表されています。今後もAWSで生成AIを活用するマネージドサービスは増えていくと思いますので、私としてもAWS全冠にあぐらをかかず最新技術をキャッチアップしていく所存です。

当社について

当社は顧客中心主義を掲げ、お客様にとって本当に価値があるソリューションの提供を目指しています。
本記事に関連するところで言えば、システム企画からピュアな機械学習によるデータ分析、クラウドコールセンターの構築や問合せ情報管理システムの開発までワンストップで提供できます。

私自身はSRE(サイト信頼性エンジニアリング)を主戦場に、お客様が抱えるITの課題抽出から企画、実行まで行っています。最近では「サイト」ではなく、「顧客」に信頼性の対象を置くCREという概念も出てきており、今後は顧客の声をKPIに設定する取り組みもチャレンジしていきたいと考えています。

もし当社に興味を持たれましたら、こちらのお問い合わせフォームよりご連絡いただければ幸いです。

参考(カテゴライズで利用したプロンプト)


下記の問い合わせ内容をカテゴライズ表に厳密に従って大カテゴリ、カテゴリ、サブカテゴリに分類してください。
また該当カテゴリのトピックサマリも30字以上50字未満で記載ください。

## 問い合わせ内容
{{お客様お申出内容}}

## 出力形式
JSONで該当するカテゴリを1〜3個出力してください
[
  {
    "大カテゴリ": "",
    "カテゴリ": "",
    "サブカテゴリ": "",
    "感情分析": "",  // Negative or Neutral or Positive
    "要約": ""
  }
]

## カテゴライズ表
大カテゴリ,カテゴリ,サブカテゴリ,サンプルシナリオ
店舗,サービス,待ち時間,注文から30分以上待たされた
店舗,サービス,スタッフの態度,スタッフが無愛想
店舗,サービス,アレルギー対応,アレルギー情報の不足
店舗,サービス,注文間違い,ヴィーガンバーガーの注文間違い
店舗,サービス,その他,該当なし
店舗,環境,雰囲気,店内のインテリアが洗練されている
店舗,環境,清潔さ,店内の清掃が行き届いていない
店舗,環境,騒音レベル,店内がうるさくて食事が楽しめない
店舗,環境,照明,店内の照明が暗すぎる
店舗,環境,その他,該当なし
店舗,設備,アクセシビリティ,車椅子でのアクセスが困難
店舗,設備,座席の快適さ,座席が狭くて快適でない
店舗,設備,Wi-Fiの利用,Wi-Fiが遅くて使い物にならない
店舗,衛生管理,手洗い設備,手洗い設備が不足している
店舗,衛生管理,清掃の頻度,トイレの清掃が不十分
店舗,衛生管理,その他,該当なし
店舗,顧客体験,訪問のしやすさ,店舗までのアクセスが困難
店舗,顧客体験,情報提供,メニュー情報が不明瞭
店舗,顧客体験,特別な要求への対応,特別な食事要求に対応できない
店舗,顧客体験,その他,該当なし
店舗,その他,該当なし,該当なし
商品企画,メニュー開発,新商品の提案,新商品のアイデアが不足
商品企画,メニュー開発,健康志向のオプション,健康志向メニューが少ない
商品企画,メニュー開発,季節限定メニュー,季節限定メニューが魅力的でない
商品企画,メニュー開発,その他,該当なし
商品企画,フィードバック管理,顧客の意見集約,顧客の意見が反映されない
商品企画,フィードバック管理,商品改善,商品の改善が見られない
商品企画,フィードバック管理,トレンド分析,最新トレンドの分析不足
商品企画,フィードバック管理,その他,該当なし
商品企画,その他,該当なし,該当なし
モバイルオーダー,システムパフォーマンス,アプリの安定性,アプリがクラッシュする
モバイルオーダー,システムパフォーマンス,注文処理速度,オンライン注文の遅延
モバイルオーダー,システムパフォーマンス,ユーザーインターフェース,アプリの操作が複雑
モバイルオーダー,システムパフォーマンス,その他,該当なし
モバイルオーダー,機能性,カスタマイズオプション,カスタマイズオプションが限られている
モバイルオーダー,機能性,アレルギー情報,アレルギー情報が不足している
モバイルオーダー,機能性,ナビゲーション,アプリのナビゲーションがわかりにくい
モバイルオーダー,機能性,その他,該当なし
モバイルオーダー,その他,該当なし,該当なし
オンラインストア,商品在庫,限定商品の在庫状況,限定グッズがすぐに売り切れる
オンラインストア,商品在庫,商品情報の更新,商品情報が最新でない
オンラインストア,商品在庫,その他,該当なし
オンラインストア,注文システム,システムの使いやすさ,オンライン注文がしにくい
オンラインストア,注文システム,注文の処理速度,オンライン注文が処理されない
オンラインストア,注文システム,注文の正確性,オンライン注文が間違っている
オンラインストア,注文システム,その他,該当なし
オンラインストア,その他,該当なし,該当なし
ポイントシステム,利用体験,ポイント加算の明確さ,ポイントが予想より少ない
ポイントシステム,利用体験,利用方法,ポイントの利用方法が分かりにくい
ポイントシステム,利用体験,利用可能商品,ポイントで交換できる商品が少ない
オンラインストア,利用体験,その他,該当なし
ポイントシステム,システム性能,システムの安定性,ポイントシステムのエラー
ポイントシステム,システム性能,アクセスの容易さ,ポイントシステムへのアクセスが難しい
ポイントシステム,システム性能,情報の透明性,ポイントの計算が不透明
ポイントシステム,システム性能,その他,該当なし
ポイントシステム,その他,該当なし
プロモーション,宣伝,SNSでの告知,SNSでのプロモーションが見つからない
プロモーション,宣伝,メールマーケティング,プロモーションメールが届かない
プロモーション,宣伝,店内告知,店内でのプロモーション告知が目立たない
プロモーション,宣伝,その他,該当なし
プロモーション,オファー,限定メニュー,限定メニューの魅力
プロモーション,オファー,その他,該当なし
プロモーション,その他,該当なし,該当なし

## 特記事項
カテゴライズ表に厳密に従ってください。存在しない項目を生成しないでください。
大カテゴリ、カテゴリ、サブカテゴリを異なる組み合わせにしないでください
そしてJSONのみ出力してください

目次

  • 挨拶
  • CI/CD導入の背景
  • 前提
  • プロジェクト構成
  • ディレクトリ構成
  • .circleci/config.yml 全体の流れ
  • 試行錯誤したところ
  • 今後の展開


挨拶

CircleCIでdocker-composeを使ってテストからAWS ECSへのデプロイまでを自動化してみたので紹介します。


CI/CD導入の背景

参加しているプロジェクトではアジャイルを取り入れ、毎月リリースするようになりました。
毎月リリースがあるということは、それだけ機能改修、追加、削除があるということで、その分テストが必要になります。リリースの作業も毎月やってきます。時間がかかります。

そこで、CircleCIを導入しテスト工程とデプロイ工程、さらには2工程間の処理を自動化することで、工数を減らしつつ品質担保を実現しました。


前提

AWS ECSのサービス/クラスターの作成や、CircleCIの登録とSet up projectまで済んでいます。
AUCではVCSにGitHubを、CI/CDツールとしてCircleCIを利用しています。どちらもAUCが構築したAWS上で動いています。
技術ブログ『AWSを利用した弊社の開発環境』


プロジェクト構成

プロジェクトは、AWS ECS上に構築され、開発はDockerを用いてRuby on Railsで行っています。テストはRSpecで行っています。

flow.png


ディレクトリ構成

.
├── .circleci
│   └── config.yml
├── Dockerfile
├── Dockerfile.ecs
├── docker-compose.ecs.yml
├── docker-compose.rspec.yml
├── docker-compose.yml
├── ecs-service.json
├── spec

docker-composeファイルは、開発用、CirlceCIのRSpec実行ジョブ用、CirlceCIのAWS デプロイジョブ用の3つに分けています。それぞれで無駄なイメージをプルしたり、不要なキャッシュを設けたりするのを省くためです。Dockerfileも同じように不要な設定を省く目的で2つに分けています。

全体の流れを紹介するために.circleci/config.ymlとデプロイに使うdocker-compose.ecs.ymlを載せています。docker-compose.rspec.ymlやDockerfileは長くなるので割愛しました。

.circleci/config.yml

version: 2.1

jobs:
  rspec:
    docker:
      - image: cimg/python:3.11.5
    working_directory: ~/repo
    steps:
      - checkout
      - setup_remote_docker
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "Gemfile.lock" }}
            - v1-dependencies-
      - run:
          name: Create Docker Network
          command: docker network create --subnet=172.19.0.0/16 itid_group
      - run:
          name: Start Docker Compose services
          command: docker-compose -f docker-compose.rspec.yml up --build -d
      - run:
          name: Create DB
          command: docker exec -it app_web bundle exec rake db:create RAILS_ENV=test
      - run:
          name: Run RSpec tests
          command: |
            docker exec -it app_web bundle exec rspec
            docker-compose down
      - save_cache:
          paths:
            - ./vendor/bundle
          key: v1-dependencies-{{ checksum "Gemfile.lock" }}

  build_image:
    docker:
      - image: cimg/python:3.11.5
    steps:
      - checkout
      - setup_remote_docker
      - run:
          name: Install AWS CLI
          command: |
            sudo pip install awscli
      - run:
          name: Build image
          command: |
            $(aws ecr get-login --no-include-email --region ap-northeast-1)
            docker-compose -f docker-compose.ecs.yml build --build-arg RAILS_MASTER_KEY=${RAILS_MASTER_KEY} --build-arg RAILS_ENV=production
            docker tag project_web ${ECR_DOMAIN}/app-web:$CIRCLE_SHA1
            docker tag project_web ${ECR_DOMAIN}/app-web:latest
      - run:
          name: Push Docker Image
          command: |
            docker push ${ECR_DOMAIN}/app-web:$CIRCLE_SHA1
            docker push ${ECR_DOMAIN}/app-web:latest
  deploy:
    docker:
      - image: cimg/python:3.11.5
    steps:
      - run:
          name: Install AWS CLI
          command: |
            sudo pip install awscli
      - run:
          name: Migration
          command: |
            aws ecs run-task \
              --region ap-northeast-1 \
              --launch-type FARGATE \
              --network-configuration "awsvpcConfiguration={subnets=["subnet-*****************", "subnet-*****************", "subnet-*****************", "subnet-*****************"],securityGroups=["********************"],assignPublicIp=ENABLED}" \
              --cluster app-ecs-cluster --task-definition app-migrate
      - run:
          name: Deploy
          command: |
            aws ecs update-service --cluster app-ecs-cluster --service app-service --task-definition app --force-new-deployment

workflows:
  version: 2
  test:
    jobs:
      - rspec
      - build_image:
          filters:
            branches:
              only: ecs_deploy
      - deploy:
          requires:
            - build_image
          filters:
            branches:
              only: ecs_deploy


docker-compose.ecs.yml

version: "3.9"
services:
  web: &web
    container_name: 'app_web'
    build:
      context : .
      dockerfile: Dockerfile.ecs
    command: bash -c "yarn install &&
             rm -f /app/tmp/pids/server.pid &&
             freshclam &&
             service clamav-daemon start &&
             bundle exec rails s -p 3000 -b '0.0.0.0'"
    ports:
      - "3000:3000"
    tty: true
    stdin_open: true
    environment:
      REDIS_URL: 'redis://localhost:6379/1'
    networks:
      - app_group
      - default
  # 毎回ビルドする必要がないため、別個ECRにpushした
  # redis:
  #   container_name: 'app_redis'
  #   image: redis:7-alpine
  #   ports:
  #     - "6379:6379"
  #   command: redis-server --appendonly yes
  sidekiq:
    <<: *web
    container_name: 'app_sidekiq'
    ports:
      - "5001:3000"
    command: bundle exec sidekiq -C config/sidekiq.yml


.circleci/config.yml 全体の流れ

  1. プロジェクトメンバーがGitHubにpushすると、CircleCIがトリガーされ、rspec jobのRSpecテストが実行されます。

  2. RSpecのテストが通ったらレビューを行います(人力)。これにパスしたら開発環境へのデプロイ用ブランチ ecs_deployにmergeします(人力)。

  3. ここで再度CircleCIが実行され、今度はrspec job実行後、build_image jobでAWS ECRにイメージが保存されます。

  4. イメージの保存が完了すると、最後にdeploy jobが実行され、ECRに保存されたイメージを利用してAWS ECSにアプリケーションがデプロイされます。

build image jobのPush Docker Imageで$CIRCLESHA1とlatest2つのタグをつけたイメージをpushしています。
latestタグがついたイメージをdeploy jobで使用しています。$CIRCLE
SHA1タグをつけるのはバージョン管理のためです。
CircleCI 定義済み環境変数

deploy jobでは、まずapp-web:latestイメージを用いてDBのマイグレーションを行っています。
その後、Deployで同じapp-web:latestイメージを用いてapp-deployタスクを実行し、app-ecs-clusterクラスターにアプリケーションをデプロイします。


試行錯誤したところ

docker-compose を利用したビルド

CircleCI導入当時、.circleci/configは直にrubyのイメージをプルして直に環境構築することを想定していましたが、開発環境はもともとDockerで構築していたため、CircleCIもdocker-composeを利用して構築することにしました。
管理するコードを減らし、ローカルとCircleCI環境の環境差がrspecテストに影響しないようにできました。

docker:
      - image: cimg/ruby:3.1.2-browsers
    steps:
      - checkout

# ↓各jobのイメージはdocker-composeをインストール済みの仮想マシンを使用するよう変更

docker:
      - image: cimg/python:3.11.5
    steps:
      - checkout
      # -setup_remote_dockerでリモート Docker環境をアクティブ化。これでdockerコマンドが使えるようになる
      - setup_remote_docker


RedisのECRイメージだけ別でpushした

ECRのイメージは本当はapp-web1つにまとめられると良かったのですが、docker-compose.ymlを利用したビルドではRedisはRedis単独のイメージとしてpushされておりapp-webイメージ、redisイメージの2つができていました。それに気づかずデプロイを進め、Redisが参照できないとエラーが出ていました。

生成されたredisイメージを使うことも考えましたが、プロジェクトで使用しているRedisは現在バージョン7で固定しており、毎回のイメージビルドは不要です。
そこで、最初に別個ECRへredis-7イメージをpushしてそれを使用するようにしました。
docker-compose.ecs.ymlでredisの部分をコメントアウトしているのはそのためです。Redisのバージョンアップがある際にはまたpushする予定です。


rspec jobのDB接続がうまくいかない

DBセットアップ前にmigrateしようとしてエラーが発生したため、migrateとseedはrspecコマンド実行時にspec/rails_helper.rb内で行われるようにしました。

エラーメッセージ

rails aborted!
ActiveRecord::NoDatabaseError: We could not find your database: app_test. Which can be found in the database configuration file located at config/database.yml.

spec/rails_helper.rb

# 一部抜粋
RSpec.configure do |config|
  config.before(:suite) do
    Rails.application.load_tasks
    # migrateにはridgepole gemを使用
    Rake.application['ridgepole:apply'].invoke
    Rails.application.load_seed
  end
end


rspec jobのsubdomain付きURLへのアクセスでNet::ReadTimeoutエラー

ローカルでのテストはパスしていたのですが、CircleCI上ではsubdomain付きURLへのアクセス箇所で失敗していました。
プロジェクトではRSpecのテストでWEBブラウザを操作するためにSeleniumを使用しています。
調べてみると、Webdriverが内部的にいろいろなドライバーと通信するのにHTTPを使用していて、その通信にはRubyの標準ライブラリであるNet::HTTPが使われているようです。このNet::HTTPのデフォルトタイムアウトが60秒になっていてそこでひっかかっているようでした。
Selenium ドキュメント

Failures:

1) 管理画面にログインする
Failure/Error: visit login_path

Net::ReadTimeout:
Net::ReadTimeout with #

Seleniumのドキュメントの通りread_timeoutを設定するとうまく通りました。

spec/support/capybara.rb

Capybara.register_driver :remote_chrome do |app|
  # 一部抜粋
  client = Selenium::WebDriver::Remote::Http::Default.new
  client.read_timeout = 240
end


今後の展開

CI/CDを導入してテストからデプロイまで一気通貫で行えるようになりました。今後の展開として以下に上げる点を改善していきたいです。


latestタグ運用の廃止

deploy jobのDeploy、Migrationでlatestタグのついたイメージを使用しているのは、コミットハッシュのタグを使う運用に変更したいです。
具体的には、ECSのタスク定義でlatestタグのついたイメージを使用するようにしていますが、毎回コミットハッシュのタグ付きのイメージを使用するようタスク定義を書き換えるようにします。
そうすることで、障害発生時の切り戻しが迅速に行えるようになるのでベストプラクティスのようです。


デプロイの前に手動承認のひと手間を加える

CircleCIには、[Approval (承認)] ボタンがクリックされるまでジョブの実行を待つ手動承認の機能があります。
現在のconfigファイルではcommitしたらすぐにテストからデプロイまで走ってしまいますが、手動承認を実装してデプロイは実行者の承認のもと行うようにしたいです。


マイグレーション前のDBバックアップ

プロジェクトではDBにRDSを使用しています。マイグレーションの前にスナップショットを撮るようにして、バックアップするようにしたいです。


Net::ReadTimeoutエラーの解消方法

今回はread_timeout = 240として解消しましたが、240秒はちょっと長すぎるので、根本原因を探り改善したいです。



Image by Freepik

目次

  • 背景
  • 原因究明
  • 解決策
  • 結果


背景

 AUCでは、SRE活動の一環として、AWSコストの適正化を行っています。
(技術ブログ『SRE:コスト抑制のための異常値検知機構の実装』)
コスト適正化における課題は、大きく分けて下記の4つです。

①コストは月末にチェックしており、月中でコストが急激に上昇した場合発見が遅れてしまう。
② 不要なリソースが放置されていたり、新たなリリースによって生じたコストを確認していない。
③ AWSが提供するベストプラクティスによるコスト適正化が行われていない。
④ コストに対する意識が薄い。

今回のブログでは、『③ AWSが提供するベストプラクティスによるコスト適正化が行われていない。』により発生していたコスト増加について行った、原因調査〜コスト削減までを記録します。

 対象となるサービスはNAT Gatewayです。直近1年間のコスト推移調査の結果、NAT Gatewayのコストが1年で約64%増加していることを検知しました。
NAT Gatewayの料金は時間単位料金とデータ処理料金の2つあります。

  • 時間単位料金:NAT Gatewayの利用時間に対して0.062USD/時 ※
  • データ処理料金:NAT Gatewayで処理されたデータ量に対して0.062USD/GB ※
    ※東京リージョンの場合(Amazon VPCの料金より)

NAT Gateway作成後、時間単位料金は一定のため、データ処理料金が増加しているであろうことが予測できます。
NAT Gatewayの通信先を特定し、NAT Gatewayを通す必要がないデータを通してしまっていないか調査します。


原因調査

 VPCフローログを使用し、取得したログをCloudWatch Logs Insightで分析することでNAT Gatewayの通信先を特定します。

1. IAMポリシーの作成

 VPCフローログを作成する前に、VPCフローログがCloudWatch LogsにアクセスできるようにIAMポリシーを作成します。 「IAM>ポリシー>ポリシーを作成」を選択し、JSONに下記コードを記載、任意のポリシー名を付けてポリシーを作成します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:DescribeLogGroups",
        "logs:DescribeLogStreams"
      ],
      "Resource": "*"
    }
  ]
}   


2. IAMロールの作成

 1で作成したIAMポリシーをVPCフローログにアタッチするためのロールを作成します。
「IAM>ロール>ロールを作成」を選択し、信頼されたエンティティタイプで『カスタム信頼ポリシー』を選択して下記コードを記載します。

スクリーンショット 2023-08-16 14.43.37.png

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "vpc-flow-logs.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
} 


許可ポリシーは1で作成したポリシーを選択し、任意のロール名を付けてロールを作成します。 スクリーンショット 2023-08-16 14.44.32.png

3. CloudWatch Logs ロググループの作成

 VPCフローログのログを入れるためのロググループを作成します。
「CloudWatch>ロググループ>ロググループを作成」を選択し、任意のロググループ名を付けてロググループを作成します。

4. VPCフローログの作成

 VPCフローログを作成するための準備が整いましたので、いよいよフローログを作成します。
VPCフローログ自体には料金は発生しませんが、CloudWatch Logs側でデータ取り込み料金が発生するため、今回のように一時的な利用の場合は通信先特定後にVPCフローログを削除することをおすすめします。

調査対象のNAT GatewayのVPCにチェックを入れ、アクションで『フローログを作成』を選択します。 スクリーンショット 2023-08-16 14.29.46.png

任意のフローログ名を入力し、それぞれ下記を選択します。

  • 送信先:CloudWatch Logsに送信
  • 送信先ロググループ:3で作成したロググループ
  • IAMロール:2で作成したロール

スクリーンショット 2023-08-16 14.32.55.png スクリーンショット 2023-08-16 15.00.51.png



5. ログの分析

 取得したログを分析してNAT Gatewayの通信先を特定します。今回は1週間分のログを分析します。
「CloudWatch>ログのインサイト」で4で作成したロググループを選択し、それぞれ下記クエリを実行します。 スクリーンショット 2023-08-17 16.46.57.png

実行クエリ

①NAT Gatewayからインターネットへの通信

  • 送信元IP/CIDR
    • 'X.X.X.X':対象NAT Gatewayのプライマリプライベート IPv4 アドレスを指定
  • 除外する宛先IP/CIDR
    • 'Y.Y.Y.Y/YY':対象VPCのCIDRを除外。複数CIDRがある場合はand not isIpv4InSubnet〜を繋げる

filter (srcAddr like 'X.X.X.X') and not isIpv4InSubnet(dstAddr, 'Y.Y.Y.Y/YY')
| stats sum(bytes) as bytesTransferred by srcAddr, dstAddr
| sort bytesTransferred desc


②インターネットからNAT Gatewayへの通信

  • 宛先IP/CIDR
    • 'X.X.X.X':対象NAT Gatewayのプライマリプライベート IPv4 アドレスを指定
  • 除外する送信元IP/CIDR
    • 'Y.Y.Y.Y/YY':対象VPCのCIDRを除外。複数CIDRがある場合はand not isIpv4InSubnet〜を繋げる

filter (dstAddr like 'X.X.X.X') and not isIpv4InSubnet(srdAddr, 'Y.Y.Y.Y/YY')
| stats sum(bytes) as bytesTransferred by dstAddr, srcAddr
| sort bytesTransferred desc


 上記クエリ実行により、データ通信量(bytesTransferred)の多い順で通信先IPアドレスの一覧が得られます。 IPアドレスの一覧をプレフィックスリストと照らし合わせたところ、①、②ともにNAT Gatewayの通信先のほとんどがS3であることが分かりました。

解決策

 先述の通り、NAT Gatewayを利用してEC2↔S3間のデータ通信を行う場合、NAT Gatewayの利用料金とデータ通信料金の2つのコストが発生します。 ブログ_VPCエンドポイント.drawio.png

しかし、VPCエンドポイント(Gatewayタイプ)を利用すると、EC2↔S3間のデータ通信コストは発生しません。
利用料金およびデータ通信料金が無料となるGatewayタイプのVPCエンドポイントが利用できるのはS3、DynamoDBのみですが、Interfaceタイプの場合も、利用料金が0.014USD/時間、データ通信料金が0.01USD/GB(※処理されるデータが1PB/月未満の場合)のため、NAT Gatewayを利用する場合と比べてかなりのコストが削減できます。 ブログ_VPCエンドポイント.drawio (1).png

S3のVPCエンドポイント(Gatewayタイプ)利用時の注意点

 VPCエンドポイント(Gatewayタイプ)を利用して、S3との通信を行う場合、注意点が2つあります。

VPCエンドポイント設定時の通信遮断

 NAT Gateway経由で接続しているS3をVPCエンドポイント(Gatewayタイプ)経由に変更する際、S3の通信は経路変更のため遮断されます。そのため、設定変更はユーザー影響が少ない時間帯に行う必要があります。

S3のバケットポリシーとVPCのエンドポイントポリシー

 S3のバケットポリシーをEIPで制御している場合は、VPC内部のPrivate IPでの制御に変更する必要があります。VPCエンドポイントを経由してS3にアクセスする場合、通信先はVPC内部のPrivate IPになるため、EIPで制御しているとVPCエンドポイントを設定しても、S3にアクセスすることができません。同様に、VPCのエンドポイントポリシーで特定のバケットへのアクセスのみを許可している場合、S3にアクセスできなくなるため、許可リストに対象のバケットを追加するなどの対応が必要になります。

結果

 EC2↔S3の通信をNAT Gateway経由ではなく、VPCエンドポイント経由としたことで、対象NAT Gatewayのコストを約70%削減することができました。

 今回はNAT Gatewayについて、コスト適正化事例をご紹介しました。
AUCでは、お客様の環境、状況に合わせたコスト適正化を進めていきます。

参考

目次

  • 挨拶
  • Amazon Connectとは?
  • 目的と経緯
  • 仕様
  • 作業手順
  • 作業内容
  • 最後に


挨拶

こんにちは、システム部の長森です。
皆様は 自動音声応答システム(IVR) を利用したことはありますか?
IVRとは Interactive Voice Response の略で、架電時に音声が流れ、番号をプッシュすると適切なオペレーターまたは次の音声に繋がるシステムのことを指します。
企業への電話問い合わせ、商品の電話注文などによく使われているシステムなので、名前は初耳でもシステム自体は知っている!という方はきっと多いはず。
今回はこのIVRを体験できるサービスをAWSが提供するAmazon Connectを中心に用いて作ってみたので、その作成過程の全貌をご紹介したいと思います。


Amazon Connectとは?

アマゾンウェブサービス、通称AWSが提供するクラウド型コンタクトセンターサービスのことです。
クラウド上にコンタクトセンター機能が備わっているため、専用機器やコンタクトセンター運用のための場所を用意せずにコンタクトセンターを構築することができます。
またAmazon Connectは先に紹介したIVRや、電話をコンピュータと統合し、両者間でのやりとりと通信を可能にするCTI(Computer Telephony Integration)、顧客からの問い合わせに対し自動でオペレーターに振り分けるACD(Automatic Call Distributor)等のコンタクトセンターの運営に必要な機能に加えて、その他豊富な機能を標準搭載しています。
Amazon Connectに備わった各種機能は拡張性も高いため、満足度の高いコンタクトセンター運用が可能です。


目的と経緯

今回IVR体験サービスを作った目的は、ズバリ「お客様にAmazon Connectを体験してもらうこと」です。

「コンタクトセンターの業務がリモートワークに対応できておらず不便...」
「顧客との応対情報をデータ化できておらず顧客分析が不十分...」
「コンタクトセンターを立ち上げたいけど構築が大変...」

上記のようなお困りごとを抱えているお客様に、即座に問題解決可能!なAmazon Connectのサービスと便利さを知っていただくため、弊社HPのサービスページにてAmazon Connectの機能の1つであるIVRを体験していただこうと考えたのが今回の作成に至った経緯となります。


仕様

今回のIVR体験サービスでは、「本日のラッキー〇〇」を知ることができる、またはSMSにおみくじが送信される占い案内IVRを制作いたしました。
着電に対して実際に人が対応することはなく、自動音声案内のみで完結する仕組みになっています。
架電後、番号案内に従って1番を押すと「ラッキースポット」、2番を押すと「ラッキー方位」、そして3番を押すと「ラッキーフード」を知ることができ、4番を押した場合は「オリジナルおみくじ」が架電元の携帯電話にSMSメッセージとして送信されるようになっています。
また、冒頭に流れる挨拶と1~3番の音声については5時~17時の時間帯と、17時~29時の時間帯で音声内容が変化するお楽しみも加えてみました。

flow_amazonconnect.jpg
たとえば、ラッキースポットを知りたい場合は以下のような流れになります。

call_example.jpg
最後に、構成図は以下になります。とてもシンプル。

AmazonConnect_Diagram.jpg

作業手順

今回のIVR体験サービスを作るにあたって、主に4つの作業をおこないました。

  1. AWSアカウントと各インスタンスの作成
  2. Amazon Connectの設定
  3. Amazon SNSの設定
  4. AWS Lambdaの設定


各作業の具体的内容について、以下で説明していきたいと思います。
具体的とは言いつつも、ところどころ情報を省略している部分があるため、実装の参考程度に見ていただければ幸いです。
それでは、さっそく見ていきましょう!


作業内容

AWSアカウントとインスタンスの作成
AWSのサービスの利用には言わずもがなAWSアカウントが必要です。
アカウントの作成が完了したら、必要となるAmazon Connect、Amazon SNS、そしてAWS Lambdaのインスタンスを作成します。


Amazon Connectの設定
作成したAmazon Connectのインスタンスの設定をおこないます。
設定として主にすべきことは、 ①電話番号の取得②問い合わせフローの作成 の2つになります。

①電話番号の取得
AWSサポートを通じて番号取得申請をし、お客様が架電するための電話番号を取得できる状態にします。
申請する場合、選択肢の2つのうちどちらかではなく、右上の「サービスの制限の緩和をお求めですか?」からケースを作成して申請しないといけません。ミニトラップです。

make_support_case.png
ケース作成後、AWSサポートの担当者から以下4点の書類提出を求められます。

  1. AWSから連携される申請書
  2. 申請者の行政機関発行の有効な身分証明書 (運転免許証、パスポートなど)
  3. 申請者と企業の関連性を示すドキュメント (社員証や、その他所属を確認できる書類)
  4. 公共料金の請求書、法務省からの企業登録証明書 (登記事項証明書など)、行政機関からの領収書、国税または地方税に関する証明書 (納税証明書など)、社会保険料の領収書などの書類


場合によっては追加の書類提出を求められることがあります。
(私が申請した際は追加書類として企業登録証明書の提出を求められました。)
これらを提出して数日すると、担当者から電話番号の取得が可能になった旨の連絡がくるので、取得手順にしたがって番号を取得すればOKです。
今回の申請では追加書類の提出、また申請の間に大型連休を挟んだこともあり、申請から取得までに約3週間がかかりました。

②問い合わせフローの作成
Amazon Connectのフローで、「電話がかかってきてから電話が切れるまで」の音声案内のフローを作成します。
先述した仕様を実際の流れとして組み立てていくイメージです。

contactflow_example.png
たとえば上記の問い合わせフローの一部では、「オペレーション時間の確認」で時間帯を判定し、判定された時間帯によって挨拶が変わるように「プロンプトの再生」を2種類に分岐させています。
その次段階である「顧客の入力を取得する」では番号案内のあとに押下される番号によって占い内容が変わるように分岐しています。
このように、機能ブロックから必要なものを選び、組み立てていくのが問い合わせフローでの作業となります。
フローが完成したら、フローを保存、公開します。
最後に電話番号の管理ページで取得した電話番号を作成した問い合わせフローに設定すれば、Amazon Connectにてやるべき作業は完了です。


Amazon SNSの設定
ここでやることも主に2つ、 ①サンドボックスの解除申請 と ②利用上限額の変更申請 が必要になります。

①サンドボックスの解除申請
Amazon SNSにはサンドボックスというものが存在し、通常の設定ではこのサンドボックスに事前登録された番号にしかメッセージの送信ができません。
今回のIVR体験サービスでは不特定多数の番号からの着電があることを想定しているので、このサンドボックスの制限解除を申請する必要があります。
Amazon Connectでの電話番号取得申請と同様に、サービスの制限の緩和としてケースを作成し、申請します。
申請の際に、「オプション」となっているまるで書かなくてもよいかのような項目を埋めずに申請すると、後日「情報不足で申請許可無理で〜す」と言われ追加情報を求められるため、最初の申請時に書けることは書いておくのがスムーズです。

②利用上限額の変更申請
Amazon SNSでは月額使用限度額というのも設定されています。
デフォルトでは限度額が$1/月になっているのですが、これでは月に約10件ほどのSMSしか送信できないため、限度額の変更を申請せねばなりません。
①のサンドボックスの申請解除と同じケース内にて申請可能なので、同時申請します。

sms_request.png
AWSから以下のようなメッセージが届いたらサンドボックスの解除、使用限度額の変更は完了です。
(限度額を$4で申請したのですが、申請内容を見て気を遣ってくれたのか$100で適用してくれました。)

support_100usd.png
ただ、このままでは限度額の「最大値」はあがったものの、設定は$1のままになっているため、さらにAmazon SNSから自分で設定する必要があります。
テキストメッセージングの優先設定から設定可能です。
今回のサンドボックス解除とSMS使用限度額変更には申請から5日ほど要しましたが、はじめからオプション事項を埋めて申請していたらきっと1日程度で完了していたと思います、トホホ...。


AWS Lambdaの設定
AWS Lambdaでは、着電した電話番号宛にSMSを送信できるコード(関数)を作成します。
(コードについては今回省略いたします...!)
コード作業を終えたら、AWS LambdaがAmazon SNSの機能にアクセスできるようにするための設定をします。
AWS Lambdaの設定にある実行ロールからAmazon SNSのポリシーをアタッチしてあげればOKです。

lambda_role.png
AWS Lambdaですべき作業は以上になります。
これだけを見ると「Lambdaでの作業はすぐ終わりそうだなぁ〜」と思われそうですが、発展途上エンジニアの私はAWS Lambdaでのコード作業に一番手間取ってしまいました。
(指導してくださったベテランの皆様方には頭が上がりません、本当にありがとうございます。)

すべての作業が終わったら、きちんとIVR体験ができるようになっているか確かめるため、実際に電話をかけてテストをします。
今回、自動音声再生、SMSメッセージ送信の両方の確認が無事とれたので、これにて作業完了です!


最後に

今回はAmazon Connectを使ってIVR体験サービスを制作しました。
制作を通して、Amazon Connectの各種構築の素早さ、設定変更の容易さ等を実感し、その利便性の高さを再認識しました。
今回は実装しませんでしたが、Amazon Connectでは着電に対してオペレーターをつなぐ機能や、顧客とオペレーターの通話分析・通話の文字起こし機能なども組み込むことができます。
さらに、Amazon Connectは従量課金制のため、上記を含めたさまざまな機能を活用しても従来のシステムに比べてコストを抑えられる、という魅力までも兼ね備えています。
読者の皆様には、Amazon Connectについて知る第1歩として今回制作した占い案内IVRを体験していただければ幸いです。
サービスページにてお客様からお電話いただけることを楽しみにしております。
Amazon Connectの導入をご検討いただいた際には、ぜひ弊社お問い合わせページからご相談ください。


目次

  • 実装前の課題
  • 採用した技術と理由
  • 実装した内容の紹介
  • 改善したこと(抑制できたコスト)


実装前の課題

SRE(Site Reliability Engineering:サイト信頼性エンジニアリング)とは、Googleが提唱したシステム管理とサービス運用に対するアプローチです。システムの信頼性に焦点を置き、企業が保有する全てのシステムの管理、問題解決、運用タスクの自動化を行います。
弊社では2021年2月からSRE活動を行っており、セキュリティ対策、サーバーのスケールイン/アウト運用化、アラートトリアージ運用化などを行っています。


そういったSRE活動をしていく上で、お客様から「AWSのコストを適正にしたい!」という要望を頂きました。
ヒアリングをしていく上で見えた課題が大きく分けると下記の4つありました。

①コストは月末にチェックしており、月中でコストが急激に上昇した場合発見が遅れてしまう。
② 不要なリソースが放置されていたり、新たなリリースによって生じたコストを確認していない。
③ AWSが提供するベストプラクティスによるコスト最適化が行われていない。
④ コストに対する意識が薄い。

 これらの課題からAWSコストにおける活動視点が2つ見えました。
1. AWSコストの異常値の検知(課題①、②) 
2. AWSコストの抑制活動(課題②、③、④)

2のAWSコストの抑制活動は現存する全てのAWSリソースに対して行う必要があり、手を付けやすく実装に時間がかからない1のAWSコストの異常値の検知を先に実装することに決めました。
(現在も2のAWSコストの抑制活動は継続中です。)


採用した技術と理由

 AWSコストの異常値の検知の実装をするにあたり条件として、全てのAWSサービスを監視できる、なるべく人の手が入らないような運用ができるといったようなことが考えられます。
そのような条件で調査をしていく上で、以下の2つのAWSサービスが候補になりました。
①Cost Anomaly Detection
②AWS Budgets


これらのAWSサービスを簡単に説明します。

Cost Anomaly Detection

機械学習によって平均コストからの偏差の異常値を検知しそれらの異常値を通知するシステム


AWS Budgets  

1ヶ月の予算を設定し、使用状況を追跡して予算を月中で超えた場合にアラートが発生する 


どちらのサービスがお客様の状況に合っているかを考えるために、各サービスの長所・短所を洗い出しました。

サービス 長所 短所
Cost Anomaly Detection

・コスト異常が発生した場合にすぐに通知される

・閾値を設定し超えたコスト異常のみを通知する

・どのコスト異常が検知されるかは機械学習任せ

・プロモーション時のスパイクなどの一過性の
 コスト異常も検知される

AWS Budgets

・全体のコストを把握しやすい

・実際のコストが予算の閾値に対してどのような
 状況かレポートが届く

・予算の設定が必要

・AWSサービス毎のコスト異常が検知できない


 これらの長所・短所を考慮した結果、月中での検知ができ、アカウントやサービス毎に詳細に設定ができる①Cost Anomaly Detectionを採用することに決定しました。 短所は運用でカバーすることを考え、設計しました。次の章で実装の詳細を記述します。


実装した内容の紹介

 今回実装に選んだサービスはCost Anomaly Detectionです。 主要な機能は以下の3つです。(2023年4月時点)

コストモニター

  • 機械学習により平均からの上昇値を異常値として検出
  • 検知する異常の種類は4つから選択(複数作成可能)


種類 詳細
AWSのサービス AWSで使用している各サービスについて個別で異常を検知する
連結アカウント 選択したアカウント(最大10個)の合計コストからの異常を検知する
コストカテゴリ 選択したコストカテゴリ(最大10個)の合計コストからの異常値を検知する
コスト配分タグ 選択したコストタグ(最大10個)の合計コストからの異常値を検知する


アラートサブスクリプション

  • 検出対象の通知要否に異常値の閾値($100、$1000など)を設定可能
  • アラート頻度は3つから選択


種類 詳細
個々のアラート 異常が検出された場合にすぐにアラートが表示される
通知にはAmazonSNSを使用
日次アラート 1日に一度アラートが表示される
通知にはEメールを使用
週次アラート 1週に一度アラートが表示される
通知にはEメールを使用


検出履歴

  • 異常値として検出された履歴
  • 検出を評価することでコストモニターの精度を向上させる


    以下にどのような仕組みでコスト異常を通知させるのか説明します。
     まず、平均からのコスト異常をコストモニターが機械学習で検知します。
    下図の例では2つの異常値を検知しています。

costanomaly.png


異常値の閾値として、アラートサブスクリプションに$50を設定したとします。
①の異常値は$30で閾値より低いため、通知されません。
②の異常値は$90で閾値より高いため、通知されます。
このようにして、通知されるコスト異常をフィルターすることができます。

通知された異常に関しては、CostExplorerやCloudWatchを使用して原因を解明し対処します。

 また、月の初めに検出履歴を使用し、コストモニターで検知した異常が正確なものであったか評価を送信します。
通知されなかった異常も検出履歴を送信する段階でチェックし、通知はされなかったもののインパクトが大きいものは通知されたものと同様の対処を行います。

以上の実装・運用によりコスト異常をキャッチし、コストを抑制することに成功しています。
最後の章でCost Anomaly Detectionによってコストが減少した例を紹介します。

改善したこと(抑制できたコスト)

 通知された異常としては、プロモーション時のスパイク起因による一過性のコスト上昇のものと、新しいAWSサービスのリリース起因によるコスト上昇があります。
プロモーション時のスパイク起因によるコスト上昇は一過性のものなので対処せず、新しいAWSサービスのリリース起因によるコスト上昇のみ対処します。

 検知したコストの例としては、リリース起因により月初にDynamoDBのコストが上昇し、Cost Anomaly Detectionがそのコスト異常を検知しました。
原因を調査したところ、WriteRequestが増加してることがわかり、不要な書き込みをしない実装を行い、月末に対処が終わりました。
このコスト異常は月$2500のコストであり、早期発見によって抑え込むことができました。

コスト異常検知の紹介は以上になります。

 コスト抑制活動は現在も行っており、抑制活動の一例としてはCloudWatchのログ出力が多く、不要なログ出力を削除することにより、月$4000のコスト削減に成功しています。
これらの活動により、コストインパクトが大きいリソースを対処していけば全体のコストが下がり、コスト異常検知の精度も上昇していくと考えています。

 全てのAWSリソースを最適化することは長い道のりですが、売上を上げることと同様に、コストを下げることも大事なことであるので、AWSインフラの有効活用・改善をこれからも続けていきたいと思っております。

このアーカイブについて

このページには、過去に書かれた記事のうちAWSカテゴリに属しているものが含まれています。

前のカテゴリはデータ分析です。

次のカテゴリはSREです。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。