<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:webfeeds="http://webfeeds.org/rss/1.0">
  <title>Cloud カテゴリ | フューチャー技術ブログ</title>
  <subtitle>Cloud カテゴリの記事一覧</subtitle>
  <icon>https://future-architect.github.io/feed_icon.png</icon>
  <logo>https://future-architect.github.io/apple-touch-icon.png</logo>
  <webfeeds:icon>https://future-architect.github.io/apple-touch-icon.png</webfeeds:icon>
  <webfeeds:accentColor>258fb8</webfeeds:accentColor>
  <link href="https://future-architect.github.io/categories/Cloud/atom.xml" rel="self"/>
  <link href="https://future-architect.github.io/categories/Cloud/"/>
  <updated>2026-08-12T15:00:00.000Z</updated>
  <id>https://future-architect.github.io/categories/Cloud/</id>
  <generator uri="https://hexo.io/">Hexo</generator>
  <entry>
    <title>AWS Certified Solutions Architect - Professional 合格体験記 - 最難関を攻めて一発合格</title>
    <link href="https://future-architect.github.io/articles/20260813a/"/>
    <id>https://future-architect.github.io/articles/20260813a/</id>
    <published>2026-08-12T15:00:00.000Z</published>
    <updated>2026-08-12T15:00:00.000Z</updated>
    <author><name>棚井龍之介</name></author>
    <content type="html"><![CDATA[<img fetchpriority="high" src="/images/2026/20260813a/aws-certified-solutions-architect-professional.png" alt="aws-certified-solutions-architect-professional.png" width="600" height="600">

<h1 id="はじめに">はじめに</h1><p>Cyber Security Innovation Group、FutureVulsチームの棚井です。</p>
<p>2026年7月25日に「AWS Certified Solutions Architect - Professional (SAP-C02)」を受験し、812点&#x2F;1000点（合格ラインは750点）で一発合格しました。</p>
<p>これまでに「AWS Certified Security - Specialty」「AWS Certified Advanced Networking - Specialty」のスペシャリティ2つと、「AWS Certified Generative AI Developer - Professional」のプロフェッショナル1つに合格してきました。残るプロフェッショナルは「Solutions Architect」と「DevOps Engineer」の2つです。</p>
<p>どちらを先に受けるか迷いました。SAP-C02を選んだ理由は、これまでの業務と資格勉強で身につけたスキルとの重複範囲が広そうだったからです。SAP-C02はネットワーク、セキュリティ、データベース、移行と、AWSの全領域を横断します。Specialtyで深掘りしたネットワークとセキュリティが、そのまま使えるのではないかという読みがありました。</p>
<p>もうひとつは、AIとの対話で「難しい方はどちらか」を聞いたところ、SAPだと返ってきたことです。どうせ両方受けるのであれば、難しい方を先に片付けて、残りを楽に進めたいと考えました。この判断がどう転んだかは、後半の「試験結果の振り返り」で書きます。</p>
<h1 id="試験の概要">試験の概要</h1><p>SAP-C02は、AWS Well-Architected Frameworkに基づいてAWSソリューションを設計し、最適化する能力を検証する試験です。受験対象者は「AWSのサービスを使用してクラウドソリューションを設計し、実装した経験が2年以上ある人」とされています。</p>
<h2 id="試験の基本情報">試験の基本情報</h2><div class="scroll"><table>
<thead>
<tr>
<th>項目</th>
<th>内容</th>
</tr>
</thead>
<tbody><tr>
<td>試験コード</td>
<td>SAP-C02</td>
</tr>
<tr>
<td>試験時間</td>
<td>180分</td>
</tr>
<tr>
<td>設問数</td>
<td>75問（採点対象65問＋採点対象外10問）</td>
</tr>
<tr>
<td>出題形式</td>
<td>択一選択問題（正解1つ・不正解3つ）、複数選択問題（5つ以上の選択肢から正解2つ以上）</td>
</tr>
<tr>
<td>受験料</td>
<td>300 USD</td>
</tr>
<tr>
<td>スコア</td>
<td>100〜1,000のスケールスコア</td>
</tr>
<tr>
<td>合格ライン</td>
<td>750点</td>
</tr>
<tr>
<td>対応言語</td>
<td>英語、日本語、韓国語、ポルトガル語（ブラジル）、中国語（簡体字）、スペイン語（ラテンアメリカ）</td>
</tr>
</tbody></table></div>
<p>未回答の設問は不正解とみなされますが、推測による回答にペナルティはありません。わからなくても必ず何かを選ぶべき、という点はほかのAWS認定と同じです。</p>
<h2 id="コンテンツ分野と出題比率">コンテンツ分野と出題比率</h2><div class="scroll"><table>
<thead>
<tr>
<th>分野</th>
<th>出題の比率</th>
</tr>
</thead>
<tbody><tr>
<td>第1分野: 複雑な組織に対応するソリューションの設計</td>
<td>26%</td>
</tr>
<tr>
<td>第2分野: 新しいソリューションのための設計</td>
<td>29%</td>
</tr>
<tr>
<td>第3分野: 既存のソリューションの継続的な改善</td>
<td>25%</td>
</tr>
<tr>
<td>第4分野: ワークロードの移行とモダナイゼーションの加速</td>
<td>20%</td>
</tr>
</tbody></table></div>
<p>比率が26%・29%・25%・20%とほぼ均等に割り振られているので、全分野を満遍なく押さえる必要があります。Specialty試験のように、特定領域が突出して配点されているわけでもありません。</p>
<p>試験ガイドのタスクステートメントは合計20あります。内訳は第1分野に5つ、第2分野に6つ、第3分野に5つ、第4分野に4つです。ネットワーク接続戦略、セキュリティコントロール、信頼性と耐障害性、マルチアカウント環境、コスト最適化、事業継続性、パフォーマンス、運用上の優秀性、移行戦略の選定、モダナイゼーションと、AWSの設計論がひととおり網羅されています。</p>
<p>これが「最難関」と言われる理由でしょう。個々のサービスの知識だけを見れば、Specialtyのほうが深いところまで問われます。SAP-C02で難しいのは、試験ガイドの構成からわかるように、全領域を横断したうえで「この要件に対する最適解はどれか」を判断する力が求められるところです。</p>
<p>加えて、公式のサンプル問題を見てもわかるとおり、問題文と選択肢がどちらも長めです。要件が何行も続いたあとに、それぞれ数行ある選択肢を比べることになるので、知識とは別に読み解く負荷がかかります。</p>
<h1 id="学習方法">学習方法</h1><p>今回は書籍とUdemyの2本立てで、わからない部分や知らないサービスはPerplexityに質問して補いました。「AWS Certified Generative AI Developer - Professional」のときは日本語の教材が限られていたので、学習計画そのものをAIと組み立てる必要がありました。SAP-C02は歴史のある試験で教材が充実しているぶん、AIの役割は教材の穴を埋めるところに落ち着きました。</p>
<h2 id="1-書籍で全分野を一通り押さえる">1. 書籍で全分野を一通り押さえる</h2><img src="/images/2026/20260813a/book.jpg" alt="book.jpg" width="226" height="320" loading="lazy">

<p>『AWS教科書 AWS認定ソリューションアーキテクトプロフェッショナル テキスト＆問題集』（煤田弘法、西城俊介、上堂薗健 著／翔泳社）を使いました。</p>
<p>この書籍を選んだのは、章立てが試験の4分野にそのまま対応しているからです。</p>
<ul>
<li>序章: 試験とサービスの基礎知識</li>
<li>第1章: 複雑な組織に対応するソリューションの設計（第1分野）</li>
<li>第2章: 新しいソリューションのための設計（第2分野）</li>
<li>第3章: 既存のソリューションの継続的な改善（第3分野）</li>
<li>第4章: ワークロードの移行とモダナイゼーションの加速（第4分野）</li>
<li>第5章: 模擬試験</li>
</ul>
<p>まず内容を一通り読み、書籍内の演習問題は全て解きました。例題68問、節末の確認問題64問、そして模擬試験1回分が収録されています。各章を読み終えるたびに節末の確認問題で理解度を測り、最後に模擬試験で全分野をまとめて解く流れになるので、知識の抜け漏れをその都度つぶしていけました。</p>
<p>説明に図がふんだんに使われているのも助かりました。マルチアカウント構成やDRの切り替えのように、構成要素の関係を文章だけで追うのが大変なところでも、図と並べて読むと構成をイメージしやすくなります。</p>
<p>特に良かったのは、この書籍が「要件を理解する→関連するサービスや機能を探す→典型的なアーキテクチャを見る」という3ステップで設計手法を説明していることです。SAP-C02の問題文はこの順番で読み解くことになるので、書籍の構成そのものが解き方の訓練になっていました。</p>
<h2 id="2-Udemyの演習問題で多くの問題パターンに触れる">2. Udemyの演習問題で多くの問題パターンに触れる</h2><img src="/images/2026/20260813a/udemy.png" alt="udemy.png" width="226" height="320" loading="lazy">

<p>『【図解付き】AWS SAP-C02完全対応 2026年版本番同等演習問題集+詳細解説』（syo @Cloud 講師）を使いました。</p>
<p>この講座の解説が詳しくて学べることは、過去の試験勉強から知っていました。「AWS Certified Security - Specialty」「AWS Certified Advanced Networking - Specialty」「AWS Certified Generative AI Developer - Professional」でも同じ講師の講座を使っており、今回で4回連続です。</p>
<p>いちばん効いたのは解説の詳しさです。各設問に、正解だけでなく不正解の選択肢にも解説が付き、問題文や選択肢に登場した用語の説明まで入っています。この種の選択式試験では選択肢がどれもそれらしく見えるので、「なぜこれは違うのか」を言語化できるかどうかが消去法の精度を決めます。知らないサービス名が出てきても、調べ直さずに解説の中で拾えました。</p>
<p>さらに、すべての解説にアーキテクチャ図かデータフロー図が付いているのもGoodポイントです。SAP-C02の問題文は状況設定が長いので、図と対応づけて読むと「この構成のどこがボトルネックか」が頭に残ります。不明点をその場で解決できるため、1問解くたびに複数の知識が入ってきます。</p>
<p>注意点として、詳しさの裏返しで、全問を解き切ろうとすると相当な時間がかかります。1問ごとに解説を読み込んでいくと、問題数のわりに進みません。演習の問題数だけを見て計画を立てると足りなくなるので、解説を読む時間まで含めて見積もっておくのが良いと思います。</p>
<h1 id="試験勉強で得た学び">試験勉強で得た学び</h1><h2 id="7つの移行戦略（7R）の使い分け">7つの移行戦略（7R）の使い分け</h2><p>第4分野の中心にあるのが、7つの移行戦略（7R）です。リホストやリファクタリングのように、いくつかの戦略名は個別に聞いたことがありました。ただ、それらが7Rとして体系化されていることは知らず、今回の試験勉強で初めて全体像を押さえられました。7つを並べて比べると、判断軸がはっきりします。</p>
<div class="scroll"><table>
<thead>
<tr>
<th>戦略</th>
<th>別名</th>
<th>何を変えるか</th>
<th>使いどころ</th>
</tr>
</thead>
<tbody><tr>
<td>リタイア（Retire）</td>
<td>—</td>
<td>廃止する</td>
<td>ビジネス価値がない、90日間インバウンド接続がない、セキュリティリスクが高い</td>
</tr>
<tr>
<td>リテイン（Retain）</td>
<td>—</td>
<td>何も変えない（移行しない）</td>
<td>データレジデンシー要件、他アプリの移行待ち、最近アップグレードしたばかり</td>
</tr>
<tr>
<td>リロケート（Relocate）</td>
<td>—</td>
<td>実行場所だけ</td>
<td>ハードウェア購入もアプリ書き換えも運用変更もせずに移す</td>
</tr>
<tr>
<td>リホスト（Rehost）</td>
<td>リフト・アンド・シフト</td>
<td>実行場所（アプリはそのまま）</td>
<td>短期間で多数のマシンを、最小のダウンタイムで移す</td>
</tr>
<tr>
<td>リプラットフォーム（Replatform）</td>
<td>リフト・ティンカー・シフト</td>
<td>一部を最適化</td>
<td>マネージド／サーバーレス化、OSアップグレード、Graviton活用、VMをコンテナへ</td>
</tr>
<tr>
<td>リパーチェス（Repurchase）</td>
<td>ドロップ・アンド・ショップ</td>
<td>製品そのもの</td>
<td>ライセンス製品をSaaSに置き換える</td>
</tr>
<tr>
<td>リファクタリング（Refactor&#x2F;Rearchitect）</td>
<td>—</td>
<td>アーキテクチャ</td>
<td>モノリスの制約が課題、俊敏性やスケーラビリティを上げたい</td>
</tr>
</tbody></table></div>
<p>覚え方として効いたのは、移行後に何が変わるかの変化量で並べることです。リタイアとリテインは移行しないので変化なし、リロケートとリホストは場所だけ、リプラットフォームは一部、リパーチェスは製品、リファクタリングはアーキテクチャそのものが変わります。この順に、移行後に変わる範囲が広がっていきます。</p>
<p>ただし、コストの高さがそのまま同じ順に並ぶわけではありません。AWSが明記しているのは「リファクタリングは移行戦略のなかで最も複雑でコストが高い」（Refactoring is the most complex and costly of the migration strategies）という点だけです。リパーチェスについては保守・インフラ・ライセンスにかかるコストを削減できると説明されているので、変化量の大きさとコストの高さを一本の線で結んで覚えないよう注意してください。</p>
<p>そしてAWSの大規模移行ガイドでは、大規模移行の一般的な戦略としてリホスト・リプラットフォーム・リロケート・リタイアが挙げられています。リファクタリングは理想的に見えますが、移行中のモダナイズを伴う最も複雑な戦略であるため、大規模移行では推奨されていません。短期間で多数のワークロードを移す要件では、技術的に一番きれいな構成が最適解になるとは限らない、というのが大規模移行の設計感覚です。</p>
<h2 id="DR戦略の4パターン、パイロットライトとウォームスタンバイの違い">DR戦略の4パターン、パイロットライトとウォームスタンバイの違い</h2><p>試験ガイドを見ると、事業継続性や信頼性のタスクステートメントとして第1分野・第2分野・第3分野に横断して含まれているのがDR（災害対策）戦略です。AWSのホワイトペーパーでは4パターンが定義されており、RTOとRPOの目安はAWS Well-Architected 信頼性の柱のREL13-BP02に数値で載っています。</p>
<img src="/images/2026/20260813a/disaster-recovery-strategies.png" alt="disaster-recovery-strategies.png" width="640" height="288" loading="lazy">

<p>（出典: AWS 災害対策ホワイトペーパー「クラウド内での災害対策オプション」）</p>
<div class="scroll"><table>
<thead>
<tr>
<th>戦略</th>
<th>分類</th>
<th>RTO</th>
<th>RPO</th>
<th>コスト</th>
<th>DRリージョンの状態</th>
</tr>
</thead>
<tbody><tr>
<td>バックアップと復元</td>
<td>アクティブ&#x2F;パッシブ</td>
<td>24時間以下</td>
<td>数時間</td>
<td>最低</td>
<td>バックアップのみ</td>
</tr>
<tr>
<td>パイロットライト</td>
<td>アクティブ&#x2F;パッシブ</td>
<td>数十分</td>
<td>数分</td>
<td>低〜中</td>
<td>データ層は稼働、アプリ層はスイッチオフ</td>
</tr>
<tr>
<td>ウォームスタンバイ</td>
<td>アクティブ&#x2F;パッシブ</td>
<td>数分</td>
<td>数秒</td>
<td>中〜高</td>
<td>全コンポーネントが縮小容量で稼働</td>
</tr>
<tr>
<td>マルチサイトアクティブ&#x2F;アクティブ</td>
<td>アクティブ&#x2F;アクティブ</td>
<td>ほぼゼロ</td>
<td>ゼロに近い</td>
<td>最高</td>
<td>全リージョンが本番構成で稼働</td>
</tr>
</tbody></table></div>
<p>REL13-BP02には「戦略は、コストと複雑さが低く、かつ RTO と RPO が長い順にリストされます」と書かれています。つまり表の並び順そのものが判断の手がかりになるので、パイロットライトのRPOがウォームスタンバイより短くなることはありません。分類で見ると、アクティブ&#x2F;パッシブのパターンが3つあり、アクティブ&#x2F;アクティブはマルチサイトの1つだけです。</p>
<p>学習していて少し迷ったのは、パイロットライトとウォームスタンバイの違いです。どちらもDRリージョンにプライマリのコピーを持つので、混同しやすいところです。AWS公式ドキュメントには、次のように書かれています。</p>
<blockquote>
<p>パイロットライトは追加のアクションを最初に実行しない限りリクエストを処理できないのに対し、ウォームスタンバイはトラフィックを (キャパシティーレベルを減らして) すぐに処理できる</p>
</blockquote>
<p>判断基準は、いま切り替えたらリクエストを処理できるかどうかです。両者の構成を図にすると次のとおりです。</p>
<p><strong>パイロットライト</strong></p>
<pre class="mermaid" data-mermaid="fdc9c72c74ae5c808705f6fb95eaf4cab9cc4b37bfa528f48252db87983255b7">flowchart LR
    subgraph PLP["プライマリリージョン"]
        APP1["アプリケーションサーバー"] --> DB1[("データベース")]
    end
    subgraph PLD["DRリージョン（フェイルオーバー時：起動＋スケールアウトが必要）"]
        APP2["アプリケーションサーバー（停止）"] -.-> DB2[("データベース（レプリカ）")]
    end
    DB1 -->|"継続的レプリケーション"| DB2

    classDef off fill:#f2f2f2,stroke:#999,color:#777
    class APP2 off</pre>

<p><strong>ウォームスタンバイ</strong></p>
<pre class="mermaid" data-mermaid="999a6775347ae081b02b77b9ce1c3feaa8d105c1ea0ce670bf0fa027c6e81cb0">flowchart LR
    subgraph WSP["プライマリリージョン"]
        APP3["アプリケーションサーバー ×5"] --> DB3[("データベース")]
    end
    subgraph WSD["DRリージョン（フェイルオーバー時：スケールアップのみ）"]
        APP4["アプリケーションサーバー ×2（縮小稼働）"] --> DB4[("データベース（レプリカ）")]
    end
    DB3 -->|"継続的レプリケーション"| DB4</pre>

<p>もうひとつ、Professionalらしい観点として印象に残ったのが、フェイルオーバーはデータプレーンで実装せよという原則です。Auto Scalingによるスケールアップはコントロールプレーンの操作なので、大規模障害時には可用性が下がりかねません。低RTOを確保したいなら、初期トラフィック分をあらかじめプロビジョニングし、追加分をAuto Scalingで処理するハイブリッドな実装が、ホワイトペーパーではトレードオフの選択肢として紹介されています。机上で動くはずの構成と、障害のときに本当に動く構成は別物だという話でした。</p>
<h2 id="S3-Intelligent-Tieringの階層と、ライフサイクルとの使い分け">S3 Intelligent-Tieringの階層と、ライフサイクルとの使い分け</h2><p>コスト最適化は第1・第2・第3分野すべてに登場します。そのなかでもS3のストレージクラス選定は、複数分野のコスト最適化タスクに関わる重要テーマです。</p>
<p>S3 Intelligent-Tieringは、アクセスパターンに応じて階層を自動で移動させる仕組みです。</p>
<div class="scroll"><table>
<thead>
<tr>
<th>階層</th>
<th>移行条件</th>
<th>取り出し時間</th>
</tr>
</thead>
<tbody><tr>
<td>高頻度アクセス</td>
<td>デフォルト</td>
<td>即座</td>
</tr>
<tr>
<td>低頻度アクセス</td>
<td>30日連続でアクセスなし</td>
<td>即座</td>
</tr>
<tr>
<td>アーカイブインスタントアクセス</td>
<td>90日連続でアクセスなし</td>
<td>ミリ秒</td>
</tr>
<tr>
<td>アーカイブアクセス（オプション）</td>
<td>90日以上アクセスなし（最大730日まで設定可）</td>
<td>3〜5時間</td>
</tr>
<tr>
<td>ディープアーカイブアクセス（オプション）</td>
<td>180日以上アクセスなし（最大730日まで設定可）</td>
<td>12時間以内</td>
</tr>
</tbody></table></div>
<p>階層の遷移を図にすると次のとおりです。実線は自動の移動、破線はオプトインの移動です。</p>
<pre class="mermaid" data-mermaid="e5d00c4b7bdc72a50cf3cd3a848581ab67ea269c8d16fc94af500762a6b2a03e">flowchart LR
    FA["高頻度アクセス"] -->|"30日連続<br/>アクセスなし"| IA["低頻度アクセス"]
    IA -->|"90日連続<br/>アクセスなし"| AIA["アーカイブ<br/>インスタントアクセス"]
    AIA -.->|"90日以上<br/>（オプトイン）"| AA["アーカイブアクセス"]
    AA -.->|"180日以上<br/>（オプトイン）"| DAA["ディープアーカイブ<br/>アクセス"]
    IA -->|"アクセスで戻る"| FA
    AIA -->|"アクセスで戻る"| FA</pre>

<p>アーカイブインスタントアクセスまでは何もしなくても効きますが、Glacier相当の2階層に落としたいなら明示的に有効化する必要があります。</p>
<p>そして128KB未満のオブジェクトはモニタリング対象外で、常に高頻度アクセス階層に置かれます。小さなファイルが大量にあるワークロードでは、Intelligent-Tieringのメリットが出ません。実務でも見落としやすい注意点だと思いました。</p>
<p>ライフサイクルポリシーとの使い分けも、あわせて整理しておきたいポイントです。アクセスパターンが読めない、あるいは変動するときはIntelligent-Tieringを選びます。逆に、アクセスパターンが明確に予測できるなら、ライフサイクルポリシーで決め打ちした方が、モニタリングと自動化の料金がかからないぶん安くなります。</p>
<p>階層移動のタイマーをリセットするアクション（<code>GetObject</code>、<code>PutObject</code>、<code>CopyObject</code>など）と、リセットしないアクション（<code>HeadObject</code>、<code>ListObjects</code>、<code>GetObjectTagging</code>など）が区別されているのも面白いところでした。メタデータを見るだけの操作は、アクセスとみなされません。</p>
<h2 id="S3-Storage-Lensの無料メトリクスと高度なメトリクス">S3 Storage Lensの無料メトリクスと高度なメトリクス</h2><p>コスト最適化を実行する前に、どこに無駄があるかを可視化する必要があります。それを担うのがS3 Storage Lensです。組織・アカウント・リージョン・バケット・プレフィックスを横断して、ストレージの使用状況を集計できます。</p>
<div class="scroll"><table>
<thead>
<tr>
<th>項目</th>
<th>無料メトリクス</th>
<th>高度なメトリクスとレコメンデーション（有料）</th>
</tr>
</thead>
<tbody><tr>
<td>クエリ可能期間</td>
<td>14日</td>
<td>15か月</td>
</tr>
<tr>
<td>集計レベル</td>
<td>バケットレベルまで</td>
<td>プレフィックスレベルまで</td>
</tr>
<tr>
<td>アクティビティメトリクス（GET&#x2F;PUT等）</td>
<td>×</td>
<td>○</td>
</tr>
<tr>
<td>ステータスコード別メトリクス（403、503等）</td>
<td>×</td>
<td>○</td>
</tr>
<tr>
<td>CloudWatchへのパブリッシュ</td>
<td>×</td>
<td>○</td>
</tr>
<tr>
<td>レコメンデーション</td>
<td>×</td>
<td>○</td>
</tr>
</tbody></table></div>
<p>第1分野のマルチアカウント環境と絡めて押さえたいのが、AWS Organizationsとの連携です。信頼されたアクセスを有効化すれば全メンバーアカウントのメトリクスを集約でき、委任管理者を指定して運用を任せることもできます。組織全体のストレージ利用状況を可視化したい場合は、Storage Lensが適しています。</p>
<h2 id="S3のゲートウェイエンドポイントとインターフェースエンドポイントの使い分け">S3のゲートウェイエンドポイントとインターフェースエンドポイントの使い分け</h2><p>VPCエンドポイントの使い分けは、第1分野のタスクステートメント「ネットワーク接続戦略を設計する」に含まれる領域です。ここは「Advanced Networking - Specialty」で押さえた知識がそのまま活きました。S3へプライベートにアクセスする方式は2つあります。</p>
<div class="scroll"><table>
<thead>
<tr>
<th>項目</th>
<th>ゲートウェイエンドポイント</th>
<th>インターフェースエンドポイント</th>
</tr>
</thead>
<tbody><tr>
<td>実装方式</td>
<td>ルートテーブルにプレフィックスリスト宛のルートを追加</td>
<td>サブネットにENIを作成しプライベートIPを割り当て</td>
</tr>
<tr>
<td>料金</td>
<td>追加料金なし</td>
<td>有料（時間課金＋データ処理料金）</td>
</tr>
<tr>
<td>セキュリティグループ</td>
<td>適用不可（アウトバウンドルールで宛先にプレフィックスリストを指定）</td>
<td>適用可</td>
</tr>
<tr>
<td>オンプレミスからの利用</td>
<td>不可</td>
<td>可（Direct Connect／VPN経由）</td>
</tr>
<tr>
<td>VPCピアリング／Transit Gateway経由</td>
<td>不可</td>
<td>可</td>
</tr>
<tr>
<td>リージョン</td>
<td>同一リージョン内のみ</td>
<td>クロスリージョン対応</td>
</tr>
<tr>
<td>AWS PrivateLink</td>
<td>使用しない</td>
<td>使用する</td>
</tr>
</tbody></table></div>
<p>経路の違いを図にすると次のとおりです。</p>
<p><strong>ゲートウェイエンドポイント</strong></p>
<pre class="mermaid" data-mermaid="0b6add0ec1e41e34e50e843a7f814123938a7b6abb3455dda07c5e00acc9a9b4">flowchart LR
    subgraph GVPC["VPC"]
        GEC2["EC2"] --> GRT["ルートテーブル"]
        GRT --> GEP["ゲートウェイ<br/>エンドポイント"]
    end
    GEP --> GS3[("Amazon S3<br/>（同一リージョンのみ）")]
    GONP["オンプレミス"] -.->|"Direct Connect / VPN<br/>経由でも利用不可"| GEP
    GPEER["ピアリング先VPC"] -.->|"利用不可"| GEP

    classDef ng stroke:#d93025,color:#d93025
    class GONP,GPEER ng
    linkStyle 3,4 stroke:#d93025</pre>

<p><strong>インターフェースエンドポイント</strong></p>
<pre class="mermaid" data-mermaid="bbda1a52e068acf7eaa3e86718c7d6fce820debe23a4f5b70d45e7e9ab201f24">flowchart LR
    subgraph IVPC["VPC"]
        IEC2["EC2"] --> IEP["インターフェース<br/>エンドポイント<br/>（ENI＋プライベートIP）"]
    end
    IEP --> IS3[("Amazon S3<br/>（別リージョンも可）")]
    IONP["オンプレミス"] -->|"Direct Connect / VPN"| IEP
    IPEER["ピアリング先VPC"] -->|"ピアリング / Transit Gateway"| IEP</pre>

<p>判断軸は明快で、VPC内からだけ使うのか、オンプレミスやほかのVPCからも使うのかで決まります。</p>
<p>VPC内のインスタンスからS3にアクセスするだけなら、ゲートウェイエンドポイントが無料なので迷う必要はありません。しかし、Direct Connect経由でオンプレミスからS3にプライベートアクセスしたい、あるいはVPCピアリング先のVPCから使いたいという要件が入った瞬間に、ゲートウェイエンドポイントは選択肢から外れます。ここでインターフェースエンドポイントが必要になります。</p>
<p>「無料だからゲートウェイ」「PrivateLinkだからインターフェース」と決め打ちせず、オンプレミスや他VPCからの利用有無とコストの両面から選ぶのが基本です。</p>
<h2 id="CloudFrontのマネージドプレフィックスリストでオリジンを保護する">CloudFrontのマネージドプレフィックスリストでオリジンを保護する</h2><p>セキュリティ領域で新たに学んだのが、CloudFrontとALBを組み合わせる際のオリジン保護です。</p>
<p>CloudFrontをALBの前に置いても、ALBのDNS名が知られていればCloudFrontを迂回して直接アクセスされてしまいます。WAFやキャッシュを回避されるので、オリジン側でCloudFrontからのアクセスだけを許可したいところです。ここで使うのがCloudFrontのマネージドプレフィックスリストです。</p>
<ul>
<li><code>com.amazonaws.global.cloudfront.origin-facing</code>（IPv4）</li>
<li><code>com.amazonaws.global.ipv6.cloudfront.origin-facing</code>（IPv6）</li>
</ul>
<p>これらはCloudFrontのオリジン向けサーバーのIPアドレス範囲を含むマネージドプレフィックスリストで、AWSが自動で最新に保ってくれます。オリジン（ALBやEC2）のセキュリティグループで、このプレフィックスリストからのインバウンドHTTPS（443）を許可し、それ以外のインバウンドルールをすべて削除します。これでCloudFront以外のトラフィックがオリジンに到達しなくなります。</p>
<p>図にすると次のようになります。</p>
<pre class="mermaid" data-mermaid="473ac0aa89c2d279b80178862be1dc9865b49c4431d69a0109378d192a66d97f">flowchart LR
    User["ユーザー"] -->|HTTPS| CF["CloudFront<br/>AWS WAF・キャッシュ"]
    CF ==>|"許可<br/>送信元がマネージドプレフィックスリスト"| ALB["ALB<br/>インバウンドは HTTPS 443 のみ<br/>ソースはプレフィックスリストだけ"]
    ALB --> Origin["オリジン<br/>EC2 / ECS"]
    Attacker["第三者"] -.->|"ALB の DNS 名を直接指定<br/>セキュリティグループで遮断"| ALB

    classDef blocked stroke:#d93025,stroke-width:2px
    class Attacker blocked
    linkStyle 3 stroke:#d93025,stroke-width:2px</pre>

<p>自前でCloudFrontのIPレンジを取得して更新していく運用は、更新漏れが即障害になるので避けたいところです。マネージドプレフィックスリストなら、その管理をAWSに寄せられます。</p>
<p>ただし注意点があります。マネージドプレフィックスリストがセキュリティグループのルール数として消費するのは1ルールではなく、そのプレフィックスリストに設定された「重み（Weight）」の分です。セキュリティグループのルール数にはクォータがあるので、重みを考慮せずに設定すると上限に引っかかることがあります。「マネージドプレフィックスリストを使えば1行で済む」と思い込んでいると、実務で踏む地雷になりそうです。</p>
<h1 id="試験結果の振り返り">試験結果の振り返り</h1><p>最終スコアは812点（合格ライン750点）で、62点上回っての一発合格でした。</p>
<img src="/images/2026/20260813a/score.png" alt="score.png" width="1200" height="438" loading="lazy">

<p>分野別の評価は次のとおりです。</p>
<div class="scroll"><table>
<thead>
<tr>
<th>コンテンツ分野</th>
<th>出題比率</th>
<th>評価</th>
</tr>
</thead>
<tbody><tr>
<td>第1分野: 複雑な組織に対応するソリューションの設計</td>
<td>26%</td>
<td>コンピテンシーを満たしている</td>
</tr>
<tr>
<td>第2分野: 新しいソリューションのための設計</td>
<td>29%</td>
<td>コンピテンシーを満たしている</td>
</tr>
<tr>
<td>第3分野: 既存のソリューションの継続的な改善</td>
<td>25%</td>
<td>コンピテンシーを満たしている</td>
</tr>
<tr>
<td>第4分野: ワークロードの移行とモダナイゼーションの加速</td>
<td>20%</td>
<td>コンピテンシーを満たしている</td>
</tr>
</tbody></table></div>
<p>4分野すべてで「コンピテンシーを満たしている」という結果になりました。</p>
<p>全分野を埋められた理由は、過去に合格した試験の勉強が効いたことだと思っています。冒頭に書いた「重複範囲が広そう」という読みは、想定以上に当たりました。第1分野のタスクステートメント1が「ネットワーク接続戦略を設計する」なので、「Advanced Networking - Specialty」の範囲がそのまま復習になりました。IAMのクロスアカウントアクセスやKMSの暗号化戦略も「Security - Specialty」と重なります。そこに書籍とUdemyで広く問題パターンに触れたことが加わり、ある分野が弱くても他分野で補うという戦い方をせずに済みました。</p>
<p>SAPはAWS認定の最難関とされますが、全領域を総合した試験なので、ほかの試験に合格してからチャレンジした方が、復習にもなって良いのかもしれません。私は「難しい方を先に片付けたい」という理由でSAPを選びましたが、結果としてはSpecialty2つとProfessional1つの合計3つを積み上げたあとにSAPを受けたことが、追い風になっていました。</p>
<p>時間配分については、見直しも含めて180分すべてを使いました。75問を180分なので1問あたり2.4分ですが、長文の状況設定を読み、選択肢を4つ（複数選択なら5つ以上）比較していると、それなりに押します。余裕があるとは言えない配分でした。</p>
<h1 id="おわりに">おわりに</h1><p>「難しい方を先に片付けて、残りを楽に進めたい」という動機で選んだSAP-C02でしたが、受け終えてみると、難しかったのは知識の深さよりも全領域を同時に扱う総合力でした。</p>
<p>その総合力は、日々のAWSクラウドインフラ業務と、ネットワーク・セキュリティ・生成AIという専門領域を1つずつ押さえてきた積み上げが形になったものだと感じています。業務で設計や運用をしている構成と出題範囲が広く重なるので、日々の仕事と試験勉強がまっすぐつながりました。「最難関」という言葉に身構えていましたが、受け終えて感じたのは、これまで学んだことと日々やっていることを、要件に合わせて選ぶ力の大切さでした。</p>
<p>次は、残るプロフェッショナルであるAWS Certified DevOps Engineer - Professionalを目指します。当初の狙いどおり難しい方を先に倒したので、ここからは積み上げた知識を活かして進められるはずです。SAP-C02で押さえたCI&#x2F;CD、IaC、Systems Manager、モニタリングと自動修復の考え方は、DevOps側と重なる部分が多いと見ています。</p>
<p>AWSのサービスは日進月歩なので、試験に合格してもキャッチアップは終わりません。</p>
]]></content>
    <summary type="html">Cyber Security Innovation Group、FutureVulsチームの棚井です。2026年7月25日に「AWS Certified Solutions Architect - Professional 」を受験し、812点/1000点（合格ラインは750点）で一発合格しました。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="AWS" scheme="https://future-architect.github.io/tags/AWS/"/>
    <category term="DR" scheme="https://future-architect.github.io/tags/DR/"/>
    <category term="S3" scheme="https://future-architect.github.io/tags/S3/"/>
    <category term="VPC" scheme="https://future-architect.github.io/tags/VPC/"/>
    <category term="合格記" scheme="https://future-architect.github.io/tags/%E5%90%88%E6%A0%BC%E8%A8%98/"/>
  </entry>
  <entry>
    <title>AWS Certified Advanced Networking - Specialty 合格体験記 - 廃止直前の駆け込み受験</title>
    <link href="https://future-architect.github.io/articles/20260708a/"/>
    <id>https://future-architect.github.io/articles/20260708a/</id>
    <published>2026-07-07T15:00:00.000Z</published>
    <updated>2026-07-07T15:00:00.000Z</updated>
    <author><name>棚井龍之介</name></author>
    <content type="html"><![CDATA[<img fetchpriority="high" src="/images/2026/20260708a/image1.png" alt="" width="600" height="600">

<h2 id="はじめに">はじめに</h2><p>フューチャーでFutureVuls（脆弱性管理SaaS）の開発に携わる棚井です。</p>
<p>2026年7月1日に AWS Certified Advanced Networking - Specialty (ANS-C01) を受験し、769点&#x2F;1000点(合格ライン750点)で一発合格しました。前回のSecurity に続く、2つ目のAWS認定です。</p>
<p>受けた動機はシンプルで、AWSネットワークの知識武装です。業務を通して断片的な知識は溜まっていましたが、体系立てて全体を見たことはありませんでした。なので、ここで一度、網羅的におさらいして固めておきたいと考えました。背中を押したのは、<strong>この試験が2026年8月25日で廃止される</strong> という告知です。ネットワークのSpecialtyがなくなる前に受けておきたかったので、廃止の約2ヶ月前に申し込みました。</p>
<p>受験の少し前、6月25日と26日には AWS Summit Japan 2026 に両日参加してきました。今年は会場全体がAIエージェントの話でした。個人的に一番刺さったのがAWS DevOps Agentです。CloudWatchのアラームなどを起点に、こちらがプロンプトを打たなくても自律的にインシデントを調査し、テレメトリやコード、デプロイ履歴を突き合わせて、原因と対処案まで出してくれるようです。</p>
<p>これを見て、ネットワークの障害調査も、これからはエージェントが担っていくのだろうと感じました。ただ、エージェントがどのメトリクスを見て、どのサービスのログを読んでいるのかを自分が分かっていないと、出てきた結果を判断できません。その中身を正しく理解しておきたいというのも、ネットワークを棚卸ししようと思った理由の1つでした。</p>
<h2 id="試験の概要">試験の概要</h2><p>ANS-C01は、AWSとオンプレをまたぐネットワークを大規模に設計し、運用し、守れるかを問うSpecialtyレベルの認定です。出題は4分野に分かれます。</p>
<blockquote>
<p>参考：AWS Certified Advanced Networking - Specialty (ANS-C01) 試験ガイド（公式）</p>
</blockquote>
<div class="scroll"><table>
<thead>
<tr>
<th>分野</th>
<th>出題比率</th>
</tr>
</thead>
<tbody><tr>
<td>ネットワーク設計</td>
<td>30%</td>
</tr>
<tr>
<td>ネットワーク実装</td>
<td>26%</td>
</tr>
<tr>
<td>ネットワークの管理と運用</td>
<td>20%</td>
</tr>
<tr>
<td>ネットワークセキュリティ、コンプライアンス、ガバナンス</td>
<td>24%</td>
</tr>
</tbody></table></div>
<ul>
<li>設問数：65問（採点対象50問、採点対象外15問）</li>
<li>試験時間：170分</li>
<li>合格ライン：1000点満点で750点</li>
<li>設問形式：択一選択、複数選択、マッチング</li>
</ul>
<p>配点が一番大きいのはネットワーク設計の30%です。実際、要件から最適な構成を選ばせる問題が中心で、帯域や冗長性、レイテンシ、暗号化、コストのどれを優先するかで答えが変わりました。</p>
<p>冒頭のとおり、この試験は2026年8月25日で受験できなくなります。廃止前に取った認定は、取得日から3年はそのまま有効です（私の場合は2029年7月まで）。ただし廃止後は新規発行も再認定もありません。AWSはここ数年でSpecialtyを絞っていて、Machine Learning - Specialtyも2026年3月末で廃止済みです。ネットワークもその流れの中にあります。</p>
<h2 id="学習方法">学習方法</h2><p>私の学習は、シンプルに2ステップでした。</p>
<h3 id="1-完全対応テキストで全体像をつかむ">1. 完全対応テキストで全体像をつかむ</h3><img src="/images/2026/20260708a/image2.jpg" alt="image2.jpg" width="281" height="400" loading="lazy">

<p>まず、AWS認定 高度なネットワーキング-専門知識(ANS-C01)完全対応テキストを1周しました。ANS-C01は日本語の教材がほとんどない試験ですが、この本は現行のANS-C01に対応した数少ない日本語専用書です。VPC、Transit Gateway、Direct Connect、VPN、CloudFrontやRoute 53、ネットワークセキュリティ、監視・運用、トラブルシューティングまで、範囲を章立てで押さえています。</p>
<p>業務のニーズに応じてつまみ食いで覚えていた内容を、試験範囲に沿って体系的に学び直しました。拠点間接続、クライアント接続、エッジと章立てで通したことで、それぞれのサービスの位置づけが整理できました。業務では触ってこなかったDirect Connect(DX)、VPC Reachability Analyzer、CloudFrontのLambda@Edgeといったサービスも、名前だけの状態から中身を押さえました。</p>
<p>役に立ったのは、むしろ古い知識のほうでした。以前マスタリングTCP&#x2F;IP 入門編（第6版）で学んだTCPやIP、ルーティング、DNSといったプロトコルの基礎です。AWSのネットワークも、結局はこの上に乗っています。パケットの中で何が起きているかを、昔Wiresharkで通信プロトコルを見るで一度追っておいたことが、そのまま理解の下敷きになりました。</p>
<h3 id="2-Udemyの演習問題で長文に慣れる">2. Udemyの演習問題で長文に慣れる</h3><img src="/images/2026/20260708a/image3.png" alt="image3.png" width="302" height="320" loading="lazy">

<p>次に、【構成図解付き】出題範囲網羅+AWS ANS-C01日本語実践問題220問 (Advanced Networking)の演習5(220問)を回しました。ほぼ全問にネットワーク構成図がつき、解説と公式ドキュメントへのリンクまである講座です。</p>
<p>解き方は前回のSecurityと同じで、正解だけでなく、誤答の選択肢がなぜ誤りかまで説明できるようにしました。そこまでやると、本番の消去法がぐっと楽になります。</p>
<p>ANS-C01は、とにかく問題文が長いのが特徴です。しかも設問ごとにネットワークの状況が違うので、長い文章を読んで、頭の中に構成図を描き直しながら答えることになります。正直、読むだけで脳が疲れます。正解を一発で当てにいくよりも、明らかにおかしい選択肢から落としていくほうが、効率的に回答できる問題もいくつか見られました。この長文への耐性は、Udemyで数を解いて慣れるしかありませんでした。</p>
<h2 id="試験勉強で得た学び">試験勉強で得た学び</h2><p>おさらいの中で理解が整理された論点を、いくつか挙げます。</p>
<h3 id="Transit-Gateway、VPCピアリング、PrivateLinkの使い分け">Transit Gateway、VPCピアリング、PrivateLinkの使い分け</h3><p>VPCをまたいでつなぐ方法は複数あり、目的で選び分けます。3つを表に並べました。</p>
<div class="scroll"><table>
<thead>
<tr>
<th>方式</th>
<th>つなぐ対象</th>
<th>CIDRの重複</th>
<th>押さえどころ</th>
</tr>
</thead>
<tbody><tr>
<td>VPCピアリング</td>
<td>2つのVPCを1対1</td>
<td>重複不可（考慮が必要）</td>
<td>接続料・データ処理料はなく、課金はデータ転送料のみ。経路は推移しない（A-B・B-CがあってもA-Cは通らない）。全VPCを相互接続するにはn(n-1)&#x2F;2本のピアリングが要る</td>
</tr>
<tr>
<td>Transit Gateway</td>
<td>多数のVPC・オンプレをハブで</td>
<td>重複不可（考慮が必要）</td>
<td>ルートテーブルで経路を制御し、アタッチメント間を推移的にルーティングできる。アタッチメントの時間料とデータ処理料が課金される</td>
</tr>
<tr>
<td>PrivateLink</td>
<td>特定のサービスだけ</td>
<td>重複可（考慮不要）</td>
<td>NLBまたはGWLBの背後のサービスに、インターフェースエンドポイント(ENI)経由でアクセスする。通信は消費側→提供側の一方向</td>
</tr>
</tbody></table></div>
<p>図にすると次のとおりです。</p>
<pre class="mermaid" data-mermaid="00f261e546bc6eab05b2f38c103e523ca4cd08654c2e455215b96dfc015b4814">flowchart TB
    subgraph PEER["VPCピアリング: 1対1・推移しない"]
        PA["VPC A"] --- PB["VPC B"] --- PC["VPC C"]
        PA -. "A→Cは通らない" .-> PC
    end
    subgraph TGWNET["Transit Gateway: ハブ・推移できる"]
        TG{"Transit Gateway"}
        V1["VPC 1"] --- TG
        V2["VPC 2"] --- TG
        V3["VPC 3"] --- TG
        ONP["オンプレミス"] --- TG
    end
    subgraph PL["PrivateLink：特定サービスのみ・CIDR重複可"]
        CONS["消費側VPC 10.0.0.0/16"] -->|"ENI経由・一方向"| PROV["提供サービス NLB/GWLB背後 10.0.0.0/16"]
    end</pre>

<p>判断の基準は、推移的な通信やオンプレミスの集約が要るか、CIDRが重複するか、サービス単位で足りるか、の3点です。VPCが2つならピアリング、増えればTransit Gateway、特定のサービスだけならPrivateLinkが目安になります。</p>
<p>参考：VPC ピアリング接続の仕組み、AWS Transit Gateway の仕組み、AWS PrivateLink とは</p>
<h3 id="Gateway-Load-Balancerでセキュリティアプライアンスを挟む">Gateway Load Balancerでセキュリティアプライアンスを挟む</h3><p>サードパーティのファイアウォールやIDS&#x2F;IPSをAWSに持ち込むとき、Gateway Load Balancer(GWLB)を使います。通信の経路上にアプライアンスを挟み、通り道で検査します。GWLBは通信をGENEVE（UDP 6081）でカプセル化してアプライアンスに渡し、検査を通ったトラフィックを戻します。</p>
<p>これを組織全体で効かせるのがハブ&amp;スポーク構成です。検査用のVPC（ハブ）にGWLBとアプライアンスを置き、各業務VPC（スポーク）からの通信をTransit Gateway経由でハブに集めます。実際にトラフィックをGWLBへ引き込む入口になるのがGWLBエンドポイント(GWLBe)で、ハブVPCのルートテーブルをGWLBeに向けることで検査経路に乗ります。外へ出る通信も、入ってくる通信も、いったんハブを通してから流します。検査点を1か所に集められるので、アプライアンスをVPCごとに置かずに済みます。</p>
<pre class="mermaid" data-mermaid="3c363b2017e80577704344ba0a80ea505735d5a1983a462c52ffc19177514e62">flowchart LR
    WA["スポークVPC A"]
    WB["スポークVPC B"]
    TGW{"Transit Gateway"}
    subgraph HUB["検査VPC（ハブ）"]
        GWLBe["GWLBエンドポイント"]
        GWLB["Gateway Load Balancer"]
        APP["セキュリティアプライアンス FW/IDS/IPS"]
        GWLBe <-->|"GENEVE / UDP 6081 で検査"| GWLB
        GWLB <--> APP
    end
    NET(("インターネット"))

    WA --- TGW
    WB --- TGW
    TGW -->|"① 外向き（アウトバウンド）"| GWLBe
    GWLBe -->|"② 検査を通ってから外へ"| NET
    NET -->|"③ 戻り（インバウンド）"| GWLBe
    GWLBe -->|"④ 検査を通ってからスポークへ"| TGW</pre>

<p>外向きは ①→②（スポーク→TGW→GWLBe→アプライアンスで検査→インターネット）、戻りは ③→④（インターネット→検査VPC→アプライアンスで検査→TGW→スポーク）と流れます。どちらの向きも、必ずアプライアンスを一度通ります。</p>
<p>検査を挟むと、戻りの通信が別のAZを通り、ステートフルなアプライアンスではセッションが切れることがあります。Transit GatewayのAppliance Modeを有効にすると、往路と復路が同じAZを通ります。</p>
<p>参考：Gateway Load Balancer とは？、一元化されたネットワークセキュリティのための Transit Gateway での Gateway Load Balancer の使用</p>
<h3 id="DNS-FirewallとNetwork-Firewallの違い">DNS FirewallとNetwork Firewallの違い</h3><p>Route 53 Resolver DNS FirewallとAWS Network Firewallは、名前は似ていますが守る層が違います。</p>
<p>DNS Firewallは、DNSの問い合わせをドメイン名で止めます。見るのはDNSクエリだけです。たとえば、感染したインスタンスがC2（指令）サーバーのドメインを名前解決しようとしたら、その解決をブロックします（既定の応答はNODATAで、設定によりNXDOMAINなども選べます）。DNSクエリにデータを埋め込んで持ち出すDNSエクスフィルトレーションの抑止にも使えます。既知の悪性ドメインは、AWSが管理するリスト（マルウェア配布元やボットネットのC2）をそのまま適用できます。効くのはRoute 53 Resolver（VPCの.2リゾルバ）を通るクエリなので、外部のDNSを直接叩かれると素通りします。そこはSG・NACLでポート53を塞いで補います。</p>
<p>Network Firewallは、実際の通信そのものを検査するVPCのファイアウォールです。ステートレスのフィルタ（IP・ポート・プロトコル、ネットワークACLに近い）に加え、ステートフルなSuricata互換のIPSや、通信中のドメイン（TLSのSNIなど）での制御もできます。たとえば、承認したドメイン以外へのHTTPSをSNIで遮断する、既知の攻撃パターンをIPSで検知して落とす、特定のIPレンジへの通信を止める、といった制御です。DNSの層ではなく、パケットが流れる経路の上で効きます。</p>
<pre class="mermaid" data-mermaid="2e937e19dfb5ac43315c2904c6a14c0c8b2dad4201e7edbb535a3947d64bcef5">flowchart TB
    subgraph DNSFW["DNS Firewall：名前解決の層"]
        E1["EC2"] -->|"DNSクエリ"| R53["Route 53 Resolver（.2）"]
        R53 --> DFW["DNS Firewall：ドメイン名で判定"]
        DFW -->|"ALLOW / BLOCK"| EXT1["外部の権威DNS"]
    end
    subgraph NETFW["Network Firewall：通信そのものの層"]
        E2["EC2"] --> NFW["Network Firewall：ステートレス→ステートフル Suricata IPS"]
        NFW -->|"IP・ポート・SNIで検査"| EXT2["宛先・インターネット"]
    end</pre>

<p>ドメインの名前解決を止めたいだけならDNS Firewall、通信そのものを幅広く検査・遮断したいならNetwork Firewallを使います。両者は補完関係で、併用も普通です。</p>
<p>参考：Resolver DNS Firewall の仕組み、AWS Network Firewall とは</p>
<h3 id="到達性の調査はReachability-AnalyzerとRoute-Analyzerで">到達性の調査はReachability AnalyzerとRoute Analyzerで</h3><p>疎通しないときの調査ツールは2つあり、見ている層が違います。</p>
<p>VPC Reachability Analyzerは、2点間が届くかを、パケットを流さず設定だけで解析します。セキュリティグループ、NACL、ルートテーブル、ゲートウェイまで含めたフルパスを追い、届かないならどこで止まっているかを指摘します。Transit Gateway経由の経路も追えますが、送信元と宛先は同一リージョンにある必要があります（リージョンをまたぐ場合はリージョンごとに調べます）。</p>
<p>Transit Gateway Network ManagerのRoute Analyzerは、TGWのルートテーブル上で経路が成立するかだけを解析します。セキュリティグループやNACLは見ません。その代わり、リージョンをまたいでピアリングしたTGW間の経路も追え、往路と復路の非対称もチェックできます。</p>
<pre class="mermaid" data-mermaid="785c0c58bf4c82ed968c809b080cc93c04e642b6a1d1a9a3eb5b658c8c2e4dc7">flowchart TB
    subgraph RA["Reachability Analyzer：1リージョン内のフルパス"]
        S["送信元"] --> SG["セキュリティグループ"] --> NL["NACL"] --> RT["ルートテーブル"] --> GW["ゲートウェイ / TGW"] --> D["宛先"]
    end
    subgraph RTA["Route Analyzer：TGWルートのみ・SG/NACLは対象外"]
        TA["TGW-A（リージョン1）"] -->|"リージョン間ピアリングも解析"| TB2["TGW-B（リージョン2）"]
    end</pre>

<p>1リージョン内でSG・NACLまで含めて疎通を追うときはReachability Analyzer、リージョンをまたぐTGWの経路を確かめるときはRoute Analyzerを使います（SG・NACLはVPC Flow Logsで別途確認します）。どちらも2点間を調べるツールで、ネットワーク全体を俯瞰するものではない、というのが正しい整理でした。</p>
<p>参考：Reachability Analyzer の仕組み、AWS Network Manager の Route Analyzer</p>
<h2 id="試験を終えて">試験を終えて</h2><p>受けてみて、一番の収穫は、ねらいどおりネットワークの知識武装ができたことでした。試験範囲を通しで一巡したことで、業務で使ってきた機能が全体のどこに位置づき、サービスどうしがどうつながっているのかが見えてきました。</p>
<p>前回のSecurityでも感じましたが、Specialtyの試験は、知っているかよりも、なぜそれを選ぶかを問うてきます。ネットワークではその傾向が特に強く、概要で挙げた要件を読み解いて、最適な一つを選ばせます。暗記だけでは届かず、選ぶ理由を言葉にできるかが問われました。</p>
<p>スコアは769点で、合格ラインの750点を19点上回っての合格でした。分野別の成績は次のとおりです。</p>
<div class="scroll"><table>
<thead>
<tr>
<th>分野</th>
<th>配点</th>
<th>評価</th>
</tr>
</thead>
<tbody><tr>
<td>第1分野：ネットワーク設計</td>
<td>30%</td>
<td>改善が必要</td>
</tr>
<tr>
<td>第2分野：ネットワーク実装</td>
<td>26%</td>
<td>コンピテンシーを満たしている</td>
</tr>
<tr>
<td>第3分野：ネットワークの管理と運用</td>
<td>20%</td>
<td>コンピテンシーを満たしている</td>
</tr>
<tr>
<td>第4分野：ネットワークセキュリティ、コンプライアンス、ガバナンス</td>
<td>24%</td>
<td>コンピテンシーを満たしている</td>
</tr>
</tbody></table></div>
<p>配点が最も大きい第1分野「ネットワーク設計」を落としながら、残りの7割で合格ラインに届いた結果でした。設計は、なぜその構成を選ぶかを最も広く問う分野で、そこを詰めきれなかったのが数字に出ています。余裕をもって超えたというより、なんとか届いた、というのが正直なところです。</p>
<h2 id="おわりに">おわりに</h2><p>身につけた知識は、ネットワークの設計や障害調査で役立ちます。設計から障害調査までをAIが担うようになっても、その出力の妥当性を自分で見極められるように、知識をアップデートし続けたいと思います。</p>
<p>廃止まではあと2ヶ月弱です。受けようか迷っている人がいたら、間に合ううちに受けておくのがいいと思います。</p>
]]></content>
    <summary type="html">2026年7月1日に AWS Certified Advanced Networking - Specialty に続く、2つ目のAWS認定です。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="AWS" scheme="https://future-architect.github.io/tags/AWS/"/>
    <category term="ネットワーク" scheme="https://future-architect.github.io/tags/Network/"/>
    <category term="合格記" scheme="https://future-architect.github.io/tags/%E5%90%88%E6%A0%BC%E8%A8%98/"/>
  </entry>
  <entry>
    <title>Artifact Registry利用料金の最適化方針と対応手順</title>
    <link href="https://future-architect.github.io/articles/20260519a/"/>
    <id>https://future-architect.github.io/articles/20260519a/</id>
    <published>2026-05-18T15:00:00.000Z</published>
    <updated>2026-05-18T15:00:00.000Z</updated>
    <author><name>大江悠斗</name></author>
    <content type="html"><![CDATA[<p>Terraform連載2026 の2本目です。</p>
<h2 id="はじめに">はじめに</h2><p>2024年新卒入社の製造エネルギーグループの大江悠斗です。</p>
<p>初めてArtifact Registryに触れたのでその内容について紹介させてください。</p>
<h2 id="Artifact-Registryとは">Artifact Registryとは</h2><p>Artifact RegistryとはGoogle Cloud環境で開発の成果物を一元管理・保管するサービスです。</p>
<p>主に以下の3つの特徴があります。</p>
<ul>
<li><strong>多様なフォーマットの統合管理</strong><br>Artifact RegistryはDockerイメージだけでなく、Node.js、Python、Java、OSパッケージなどのあらゆる成果物を1つの場所で統合して管理できます。</li>
<li><strong>CI&#x2F;CDパイプラインとのシームレスな連携</strong><br>GitHub ActionsやCloud BuildなどのCI&#x2F;CDと連携して、「自動でビルドされArtifact Registryに保存」「そこからCloud Runなどの実行環境へ自動デプロイされる」という高速で自動化された開発サイクルを簡単に構築できます。</li>
<li><strong>強固なセキュリティとサプライチェーンの保護</strong><br>単なるファイルの保管庫ではなく、セキュリティを担保する機能が組み込まれています。<ul>
<li><strong>脆弱性スキャン</strong><br>保存されたコンテナイメージに対して、自動でスキャンを行い、既知の脆弱性が無いかをチェックします。</li>
<li><strong>厳密なアクセス制限</strong><br>IAMを使って細かい権限管理が可能です。</li>
</ul>
</li>
</ul>
<h2 id="背景と課題">背景と課題</h2><p>Google Cloud環境でCloud Run、Cloud Functionsやdbtなどを利用していると、デプロイのたびにArtifact Registryへ新しいコンテナイメージが自動保存されます。</p>
<p>しかし、Artifact Registryのデフォルト設定では古いイメージが自動削除されません。そのため、放置しておくとストレージ容量が右肩上がりに増加し、利用料金が増大してしまうという課題がありました。</p>
<p>このコストを最適化するため、不要な旧世代イメージを自動削除する <strong>クリーンアップポリシー</strong> を導入することにしました。</p>
<h2 id="仕様理解に苦労した点">仕様理解に苦労した点</h2><p>ここが今回、私が一番苦戦した点です。</p>
<p>当初、私は「保持したい世代数」を指定すれば、それ以外は自動で消えるものだと思い「保持ポリシー（KEEP）」のみを設定していました。しかし、公式ドキュメントの削除ポリシーを作成するにも記載がある通り、「保持ポリシー」を設定しただけでは、削除処理は実行されません。</p>
<p>Artifact Registryのクリーンアップポリシーは、以下の2つをセットで適用する必要があります。</p>
<ul>
<li><strong>KEEP ポリシー</strong>: 最新のN世代など、消したくないものを <strong>「保護」</strong> する</li>
<li><strong>DELETE ポリシー</strong>: 条件に合致するものを <strong>「削除」</strong> する</li>
</ul>
<p>つまり、 <strong>「KEEPで守られていないものを、DELETEで消す」</strong> という2段階の論理構成になっていることに気づかず、「設定を入れたのにイメージが全く消えない……」と頭を抱えることになりました。</p>
<img fetchpriority="high" src="/images/2026/20260519a/Gemini_Generated_Image_.png" alt="Gemini_Generated_Image_.png" width="1200" height="603">

<h2 id="参考：環境ごとの設計方針">参考：環境ごとの設計方針</h2><p>参考までに、今回の導入に当たってはコストとリスクのバランスを考慮し、以下の方針で環境ごとに保持世代数を使い分けました。</p>
<ul>
<li><strong>開発環境</strong>: コスト最小化を優先し最新バージョンのみ保持</li>
<li><strong>本番環境</strong>: 障害発生時などに確実な復旧ができるよう安全性を確保</li>
</ul>
<p>このように何でもかんでも削除するのではなく、「万が一の時、環境ごとにどこまで戻せるべきか」というビジネス継続性の視点をもって設定をしました。</p>
<h2 id="Terraformによる実装例">Terraformによる実装例</h2><p>汎用的な Terraform コードの例を紹介します 。ポイントは、保持したい条件（KEEP）と、それ以外を削除する条件（DELETE）の両方を定義することです。</p>
<figure class="highlight tf"><table><tbody><tr><td class="code"><pre><span class="keyword">resource</span> <span class="string">&quot;google_artifact_registry_repository&quot;</span> <span class="string">&quot;example_repo&quot;</span> {
  project       = <span class="string">&quot;your-project-id&quot;</span> <span class="comment"># プロジェクトIDは環境に合わせて変更してください</span>
  location      = <span class="string">&quot;asia-northeast1&quot;</span> <span class="comment"># ロケーションを指定してください</span>
  repository_id = <span class="string">&quot;example-repo&quot;</span>
  format        = <span class="string">&quot;DOCKER&quot;</span>
<span class="line"></span>
  <span class="comment"># ★重要: 意図しない削除を防ぐため、初回適用時は true (ドライラン) を推奨</span>
  cleanup_policy_dry_run = true
<span class="line"></span>
  <span class="comment"># ポリシー1: 世代数保持 (KEEP)</span>
  <span class="comment"># 最新の5世代を保護対象とする例</span>
  cleanup_policies {
    id     = <span class="string">&quot;keep-latest-versions&quot;</span>
    action = <span class="string">&quot;KEEP&quot;</span>
    most_recent_versions {
      keep_count = <span class="number">5</span>
    }
  }
<span class="line"></span>
  <span class="comment"># ポリシー2: 削除 (DELETE)</span>
  <span class="comment"># KEEPで保護されていない、すべてのタグ状態（ANY）のイメージを削除対象とする</span>
  cleanup_policies {
    id     = <span class="string">&quot;delete-old-versions&quot;</span>
    action = <span class="string">&quot;DELETE&quot;</span>
    condition {
      tag_state = <span class="string">&quot;ANY&quot;</span>
    }
  }
}</pre></td></tr></tbody></table></figure>

<p>※本記事のコードはTerraform <code>v1.1.0</code> 以上、Google Cloud Provider <code>v6.4.0</code> にて動作確認しています。</p>
<h2 id="導入時の注意点">導入時の注意点</h2><p>設定を反映させる際、以下の点に注意するとスムーズです。</p>
<ul>
<li><strong>ドライランの活用</strong>: <code>cleanup_policy_dry_run = true</code> に設定すると、実際の削除は行われず、Cloud Logging に削除対象の候補が出力される</li>
<li><strong>反映タイミング</strong>: 設定後、即座に削除が始まるわけではなく、Google Cloud のバックグラウンド処理により最大24時間程度かかる場合がある</li>
<li><strong>権限</strong>: ログで削除対象を確認するには、プライベート ログ閲覧者 (<code>roles/logging.privateLogViewer</code>) 権限などが必要になる場合がある</li>
</ul>
<p>ログエクスプローラーで以下のクエリを実行すると、削除候補のイメージ一覧を確認できます。</p>
<figure class="highlight properties"><table><tr><td class="code"><pre><span class="line"><span class="attr">protoPayload.serviceName</span>=<span class="string">&quot;artifactregistry.googleapis.com&quot;</span></span><br><span class="line"><span class="attr">protoPayload.methodName</span>=<span class="string">&quot;google.devtools.artifactregistry.v1.ArtifactRegistry.BatchDeleteVersions&quot;</span></span><br></pre></td></tr></table></figure>

<p>※ドライランの挙動はデータアクセス監査ログとして出力されます。事前にArtifact Registry APIのログ取得を有効にしておく必要があります。</p>
<h2 id="さいごに">さいごに</h2><p>今回は Artifact Registry のコスト最適化について紹介しました。</p>
<p>単純な「保持設定」だけでは削除が行われないという仕様は、初見では少し分かりにくいポイントかもしれません。仕組みを理解してしまえば Terraform で一括管理できる便利な機能ですので、コスト増に悩んでいる方はぜひ試してみてください。</p>
<p>この記事が、同じように「イメージが消えない！」と悩む方の助けになれば幸いです。</p>
<h2 id="参考">参考</h2><ul>
<li>Artifact Registry のクリーンアップ ポリシーの管理</li>
</ul>
]]></content>
    <summary type="html">初めてArtifact Registryに触れたのでその内容について紹介させてください。Artifact RegistryとはGoogle Cloud環境で開発の成果物を一元管理・保管するサービスです。主に以下の3つの特徴があります。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="GoogleCloud" scheme="https://future-architect.github.io/tags/GoogleCloud/"/>
    <category term="Terraform" scheme="https://future-architect.github.io/tags/Terraform/"/>
  </entry>
  <entry>
    <title>AWS設計ガイドラインを公開しました</title>
    <link href="https://future-architect.github.io/articles/20251212a/"/>
    <id>https://future-architect.github.io/articles/20251212a/</id>
    <published>2025-12-11T15:00:00.000Z</published>
    <updated>2025-12-11T15:00:00.000Z</updated>
    <author><name>神崎 林太郎</name></author>
    <content type="html"><![CDATA[<img fetchpriority="high" src="/images/2025/20251212a/top.jpg" alt="" width="1024" height="559">

<h2 id="はじめに">はじめに</h2><p>Technology Innovation Groupの神崎です。</p>
<p>フューチャー社内の有志のメンバーでAWS設計ガイドラインを作成しました。</p>

<img src="/images/2025/20251212a/index.png" alt="" width="488" height="317">


<p>この記事では、ガイドライン策定の目的と、その内容を抜粋して紹介します。</p>
<h2 id="ガイドライン策定の目的">ガイドライン策定の目的</h2><p>詳細はガイドライン冒頭に記載していますが、ベストプラクティスを形式知化していくというのが第一の目的です。第二に、設計のベースラインを提供することで、システム固有で考えるべきところ（すなわち設計作業で重要なところ）に時間が使えるようにして、結果として設計品質を底上げできることを目指しています。</p>
<p>そのため、システムを跨いで再利用可能な部分に特に着目しています。</p>
<p>ちなみに、Geminiにガイドラインの目的を問うたところ次の回答でした。上記の思いやエッセンスは取り込めているのではないかと思います。</p>
<blockquote>
<p>クラウドファーストが標準となり、システム構築においてAWSを採用することは特別なことではなくなりました。しかし、各プロジェクトにおいて以下のような「非機能要件」や「共通コンポーネント」の設計議論が繰り返されている現状があります。</p>
<ul>
<li>マルチアカウント環境の境界線（OU設計）はどうあるべきか</li>
<li>監査ログ（CloudTrail等）の集約とコスト最適化のバランス</li>
<li>ワークロード（Web API&#x2F;バッチ）に応じた適切なコンピューティングリソースの選定</li>
</ul>
<p>これらはシステムごとの差異が本来少ない領域です。ここを毎回ゼロベースで検討することは、いわゆる「車輪の再発明」に他なりません。<br>設計者が本来注力すべきは、そのシステム固有のビジネスロジックやドメイン要件の実現です。</p>
<p>本ガイドラインは、これら共通化可能な設計領域を <strong>「形式知」</strong> として体系化し、設計品質の均質化と開発生産性の向上を目的として策定されました。</p>
</blockquote>
<h2 id="ガイドラインの内容のご紹介">ガイドラインの内容のご紹介</h2><p>ガイドラインの主要なポイントを要約して紹介します。</p>
<h3 id="マルチアカウントを利用した環境分離パターン">マルチアカウントを利用した環境分離パターン</h3><p>アカウントの移譲や引き渡しも意識した環境分離パターンを解説しています。</p>
<p>どのようなリソースについてアカウントを分離すべきか、どのような階層構造でアカウントを作るべきかを整理しています。</p>
<p><strong>関係するサービス</strong>:</p>
<ul>
<li>AWS Organizations</li>
<li>AWS IAM</li>
<li>AWS Control Tower</li>
</ul>
<h3 id="すべてのアカウントが対応すべきセキュリティ対策">すべてのアカウントが対応すべきセキュリティ対策</h3><p>最低限、開発・検証環境であっても講じるべきセキュリティ対策について整理しています。<br>ガイドラインを機械的に適用するのではなく、インシデントや設定不備の検知に必要な設定や、検知された際の対応手順を記載しています。</p>
<p><strong>関係するサービス</strong>:</p>
<ul>
<li>AWS Security Hub CSPM</li>
<li>AWS CloudTrail</li>
<li>Amazon GuardDuty</li>
<li>Amazon Inspector</li>
<li>Amazon Macie</li>
</ul>
<h3 id="取り扱う情報の機密性や種別、各種監査基準やセキュリティ基準への対応の仕方">取り扱う情報の機密性や種別、各種監査基準やセキュリティ基準への対応の仕方</h3><p>前述のセキュリティ対策に加え、厳密な監査基準やセキュリティ基準へ準拠する必要がある場合の対応方針を解説しています。利用するサービスとしては上の章と共通するところは多いですが、この章独自の要素として、データをどのように取り扱えば各基準に準拠できるかまでを整理しています。</p>
<p><strong>関係するサービス</strong>:</p>
<ul>
<li>AWS Security Hub CSPM</li>
<li>AWS Config</li>
<li>AWS CloudTrail</li>
<li>Amazon GuardDuty</li>
<li>Amazon Inspector</li>
<li>Amazon Macie</li>
<li>AWS Firewall Manager</li>
<li>AWS IAM Access Analyzer</li>
</ul>
<h3 id="コストの最適化">コストの最適化</h3><p>コスト最適化の手段として、どのような観点（ディメンション）で可視化を進めるべきか、推奨事項をまとめています。また、大きくコストを削減するための手段としてリセーラーの活用や、コンピュートとストレージの最適化手段などを解説しています。</p>
<p><strong>関係するサービス</strong>:</p>
<ul>
<li>Savings Plans</li>
<li>Amazon S3</li>
</ul>
<h3 id="踏み台サーバー">踏み台サーバー</h3><p>VPC内でのオペレーションを安全に行うためにどのようなサービスを利用すべきかを解説しています。</p>
<p><strong>関係するサービス</strong>:</p>
<ul>
<li>Amazon EC2</li>
<li>AWS Systems Manager (Session Manager)</li>
<li>EC2 Instance Connect Endpoint</li>
</ul>
<h3 id="アプリ特性に応じたアーキテクチャパターン">アプリ特性に応じたアーキテクチャパターン</h3><p>Web API、バッチ処理、非同期処理（キュー）など、様々なユースケースごとに、どのようなサービスが利用できるのかを整理しています。また、各方式のメリット・デメリットを比較した上で、処理特性や要件に応じて推奨値について解説しています。</p>
<p><strong>関係するサービス</strong>:</p>
<ul>
<li>Amazon API Gateway</li>
<li>Amazon CloudFront</li>
<li>Elastic Load Balancing (ALB &#x2F; NLB)</li>
<li>AWS Lambda</li>
</ul>
<h3 id="CloudWatch">CloudWatch</h3><p>CloudWatchの特性を踏まえたロググループの推奨利用方法や、各サービスで何を監視すべきなのかの指針をまとめています。</p>
<p><strong>関係するサービス</strong>:</p>
<ul>
<li>Amazon CloudWatch</li>
</ul>
<h3 id="CI-CD">CI&#x2F;CD</h3><p>AWSリソースを作成するCI&#x2F;CDパイプラインとしてどのようなサービスが利用できるのかを整理した上で、推奨値を解説しています。併せてCIとCDの分離のパターンについても指針をまとめています。</p>
<p><strong>関係するサービス</strong>:</p>
<ul>
<li>AWS CodePipeline</li>
<li>AWS CodeBuild</li>
<li>AWS CodeArtifact</li>
<li>Amazon ECR</li>
</ul>
<h2 id="さいごに">さいごに</h2><p>今回紹介した内容はガイドラインの一部です。社内のメンバーはもちろん、社外の方々にも設計のベースラインとしてご活用いただければ幸いです。</p>
<p>またフィードバックやPRについてもお待ちしております。</p>
<ul>
<li>GitHub: future-architect&#x2F;arch-guidelines</li>
<li>Future Architecture Guidelines</li>
</ul>
<p>最後に、本ガイドラインの作成に貢献頂いた有志のみなさんに感謝します。</p>
<p>第一版の完成から本記事の公開まで期間が空いてしまったため、その間のサービスアップデートに追従するためのPRが必要となりました。記事公開と前後しますが、対応するPRを用意しています。他にも、「ここ、もう古くなってるよ」という内容を見つけられましたらぜひPR頂けますと大変ありがたいです。</p>
<p>ちなみに記事執筆に当たって初めてGeminiに案出しや校正をやらせてみたのですが、その過程で自分の過去記事からトンマナを学習させました。あくまでGeminiの視点ですが、自分でも気づいてない評価が見えるので面白いですね。客観的、と言えるぐらいまで生成AIを信用はしていないのですが、確かにあんまり意識はしていないけれど大事にしていることをピックアップされてるなと思いました。もしかしたら占いが当たる、みたいな心理的効果かもしれないのですが…。</p>
<p>まだオールドな人間なので、結構紙とボールペンで自分の思考を整理してから、Geminiと壁打ちしてアイデアを膨らませるみたいな使い方をよくするのですが、Gemini 3になってからトンチンカンなこという回数が実感としても減ったように感じます。</p>
<blockquote>
<ul>
<li><strong>文体:</strong> 基本は「です・ます」調ですが、非常に論理的で硬派なスタイルです。</li>
<li><strong>構成:</strong><ul>
<li><strong>TL;DR</strong>（要約）を冒頭に配置し、結論を急ぐ読者への配慮がある。</li>
<li><strong>「頭の体操編」「実践編」</strong>といったセクション分けで、理論（Why）と実装（How）を明確に分離している。</li>
<li><strong>客観性と論理性:</strong> 「感覚値的にはこうだろう」で終わらせず、Well-Architected Frameworkなどの一次情報を引用し、論理的に正解を導き出そうとする姿勢が強い。</li>
<li><strong>感情表現の抑制:</strong> 絵文字や過度な感嘆符（！）は控えめで、技術的な誠実さを前面に出している。</li>
</ul>
</li>
</ul>
<p><strong>結論としての適用トーン:</strong><br>前回の案よりも「感情的な盛り上げ」を削ぎ落とし、より「ファクトベース」で「論理構成が明確」なスタイルに修正します。</p>
</blockquote>
]]></content>
    <summary type="html">フューチャー社内の有志のメンバーでAWS設計ガイドラインを作成しました。この記事では、ガイドライン策定の目的と、その内容を抜粋して紹介します。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="AWS" scheme="https://future-architect.github.io/tags/AWS/"/>
    <category term="ガイドライン" scheme="https://future-architect.github.io/tags/%E3%82%AC%E3%82%A4%E3%83%89%E3%83%A9%E3%82%A4%E3%83%B3/"/>
  </entry>
  <entry>
    <title>Google Cloud Next Tokyo'25 Day1参加レポート</title>
    <link href="https://future-architect.github.io/articles/20250917a/"/>
    <id>https://future-architect.github.io/articles/20250917a/</id>
    <published>2025-09-16T15:00:00.000Z</published>
    <updated>2025-09-16T15:00:00.000Z</updated>
    <author><name>片岡久人</name></author>
    <content type="html"><![CDATA[<h2 id="はじめに">はじめに</h2><p>こんにちは。フューチャーアーキテクト 製造・エネルギーサービス事業部の片岡です。</p>
<p>2025年8月5日に開催された「Google Cloud Next Tokyo ‘25」のDay1に参加してきました。このようなイベントへの参加は初めてであり、どんなものかあまり想像できていませんでしたが、勉強になり楽しめたイベントでしたので、所感の共有ができればと思います。</p>
<p>本記事では、特に印象に残った基調講演のアップデートや、参加したセッションの記録、そして来年参加される方向けのTipsなどをまとめていきます。</p>
<p>同じイベントに参加した、弊社メンバーによる別視点のレポートもございますので、ぜひ合わせてご覧ください。</p>
<ul>
<li>Google Cloud Next Tokyo’25 Day2 参加レポート</li>
<li>Google Cloud Next 2025を通して感じたAIエージェント活用の現在地</li>
</ul>
<h2 id="基調講演ハイライト：国内のAI活用を加速させる2つの重要なアップデート">基調講演ハイライト：国内のAI活用を加速させる2つの重要なアップデート</h2><p>基調講演には多くの発表がありましたが、特に私の業務と関連があり、大きな影響があると感じたアップデートを2つご紹介します。</p>
<ul>
<li>参考： Day1基調講演動画</li>
</ul>
<h3 id="1-Vertex-AI-が国内リージョンで利用可能に">1. Vertex AI が国内リージョンで利用可能に</h3><p>Vertex AIの各種機能が東京・大阪リージョンに閉じて利用できるようになりました。</p>
<p>これまで、データの国外持ち出しに関するセキュリティポリシーやコンプライアンス要件が障壁となり、生成AIの本格活用に踏み出せなかった企業は少なくなかったのではないでしょうか。特に金融、公共、医療といった厳格なデータガバナンスが求められる業界において、このアップデートはAI活用のハードルを1つ下げる要素となると感じました。</p>
<p>これにより、国内企業はデータを国外に転送することなく、Vertex AIの基盤モデルや各種ツールを利用したAI開発が可能になります。</p>
<h3 id="2-Google-Distributed-Cloud-GDC-上でGeminiが利用可能に">2. Google Distributed Cloud (GDC) 上でGeminiが利用可能に</h3><p>もう一つの注目は、GDC上でGeminiが利用できるようになったことです。GDCは、Google Cloudのインフラとサービスをオンプレミスやエッジ環境で利用できるようにするソリューションです。</p>
<p>これまでクラウドへのデータ送信がレイテンシやセキュリティの観点から難しかった領域でも、高度なAI処理をセキュアかつ低遅延で実行できる道が拓かれました。エッジAIの可能性を大きく広げる、非常にインパクトのある発表でした。</p>
<h3 id="3-所感">3. 所感</h3><p>上記の2つの発表より、Googleが日本のエンタープライズが持つセキュリティ課題に対応してきているということがわかります。</p>
<p>日本の企業、特に金融や公共機関では、データ主権や各種ガイドラインへの準拠がクラウドAI活用の高いハードルとなっていると思います。今回のアップデートは、「クラウド上のデータ（Vertex AI）」と「オンプレミス・エッジのデータ（GDC）」という両面から、その懸念を払拭しようとしていると思います。</p>
<p>このようなセキュリティ的な障壁を一つひとつ取り除いていくGoogleの動きはAI活用に当たり要Checkだなと思いました。</p>
<h2 id="参加セッションレポート">参加セッションレポート</h2><p>数多くのセッションがありましたが、特に良かったセッションをご紹介します。</p>
<h3 id="【セッションレポート】TBS-が挑むマルチクラウド運用と今後の展開">【セッションレポート】TBS が挑むマルチクラウド運用と今後の展開</h3><p>TBSテレビ様が、従来のオンプレミス中心のインフラからGCPへ移行し、さらにその運用を内製化（自律運用）していくまでの道のりを紹介するセッションでした。</p>
<p>単なる成功事例の紹介に留まらず、内製化を実現するためにどのような計画を立てて、どのように実施していったのかが具体的に説明されており、同じように内製化を目指す多くの企業・その伴走支援をする企業にとって、大いに参考になる内容だったと思います。<br>クラウド基盤構築のロードマップとして「知る」「わかる」「できる」といった3つのステップに分解し、それぞれのステップの中で具体的にどんなことを実施していったのかがわかり、内製化の現場の「生々しさ」が伝わってくる内容で非常に満足度の高いセッションでした。</p>
<p>参考： Ops Today様でも本セッションに関するレポートがOps Todayで公開されていますので、ご興味のある方はこちらもご覧ください。</p>
<h2 id="来年参加される方へ：Next-Tokyoを120-楽しむためのTips">来年参加される方へ：Next Tokyoを120%楽しむためのTips</h2><p>最後に、これから参加される方に向けて、会場で感じたTipsをいくつか共有します。<br>（来年度は状況が変わっているかもしれないため、参考情報として活用してください。）</p>
<ul>
<li><p>先着特典が欲しい場合は、早めの到着が吉。</p>
<ul>
<li>イベント開始30分前の到着では、すでに配布が終了していました。確実に手に入れたい方は、開場時間を目指してみてはいかがでしょうか。</li>
</ul>
<img fetchpriority="high" src="/images/2025/20250917a/image.png" alt="image.png" width="390" height="280">

<ul></li>
</ul>
<div class="note-container note-info"><span class="note-icon"></span><div><p>サウナ好きの筆者としてはできればゲットしたかったです、、、</p></div></div>

  </ul>

<ul>
<li>人気セッションは「予約必須」かつ「早めの着席」を<ul>
<li>1週間前では、ほとんどのセッションが満席となっていました。</li>
<li>注目度の高いセッションは、事前予約なしでの参加は難しそうです。イベント公式サイトをこまめにチェックし、予約開始したら早めに申し込みましょう。</li>
<li>また、予約していても油断は禁物です。開始時間ギリギリに行くと、立ち見になったり、音声ガイド（インカム）が足りなくなったりするケースがあります。セッション開始15〜20分前にはブースに到着しておくと、快適に聴講できると思います。</li>
</ul>
</li>
<li>「ランチ難民」にならないための事前準備<ul>
<li>会場内のフードコートやカフェは、ランチタイム（12時〜13時頃）には非常に混雑し、長蛇の列ができます。時間を有効活用するためにも、軽食を持参するか、少し時間をずらして利用するのが良いかなと思いました。</li>
</ul>
</li>
<li>水分補給は心配無用<ul>
<li>会場の各所にお水とお茶が提供されるブースが各階にありました。これは非常にありがたいポイントです。こまめな水分補給を忘れずに。</li>
</ul>
</li>
</ul>
<h2 id="おわりに">おわりに</h2><p>Google Cloud Next Tokyo ‘25 Day1は、AI、特に生成AIがより身近なものとなり、具体的なビジネス活用フェーズへと本格的に移行し始めたことを強く実感する1日でした。</p>
<p>Day2のレポートや、イベント全体を通して見えてきたAIエージェントの現在地についての考察記事も、ぜひご覧いただけると幸いです。</p>
]]></content>
    <summary type="html">2025年8月5日に開催された「Google Cloud Next Tokyo '25」のDay1に参加してきました。このようなイベントへの参加は初めてであり、どんなものかあまり想像できていませんでしたが、勉強になり楽しめたイベントでしたので、所感の共有ができればと思います。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="GoogleCloud" scheme="https://future-architect.github.io/tags/GoogleCloud/"/>
    <category term="GoogleCloudNext" scheme="https://future-architect.github.io/tags/GoogleCloudNext/"/>
    <category term="GoogleCloudNext2025" scheme="https://future-architect.github.io/tags/GoogleCloudNext2025/"/>
    <category term="参加レポート" scheme="https://future-architect.github.io/tags/%E5%8F%82%E5%8A%A0%E3%83%AC%E3%83%9D%E3%83%BC%E3%83%88/"/>
  </entry>
  <entry>
    <title>Google Cloud Next Tokyo'25 Day2 参加レポート</title>
    <link href="https://future-architect.github.io/articles/20250826a/"/>
    <id>https://future-architect.github.io/articles/20250826a/</id>
    <published>2025-08-25T15:00:00.000Z</published>
    <updated>2025-08-25T15:00:00.000Z</updated>
    <author><name>村井 俊介</name></author>
    <content type="html"><![CDATA[<h2 id="はじめに">はじめに</h2><p>みなさん、初めまして。入社1年目、製造・エネルギー事業部の村井 俊介です。</p>
<p>2025年8月5日(火)、6日(水)に東京ビッグサイトで開催されたGoogle Cloud Next Tokyo’25に参加してきましたので、当日の様子をレポートします！</p>
<h2 id="イベント概要">イベント概要</h2><p>Google Cloud Next Tokyo’25は、生成AIやAIエージェントをはじめとする最新のクラウド技術や、それらを活用した企業の事例が集結したイベントです。</p>
<p>イベントは主に以下の要素で構成されていました。</p>
<ul>
<li><strong>基調講演</strong>: Google Cloudの最新ソリューションやプロダクトが紹介されました</li>
<li><strong>セッション</strong>: AI時代の開発スタイルや、Google Cloud製品を活用した企業の成功事例が紹介されました</li>
<li><strong>EXPO</strong>: 参加企業のブースやライブデモ、展示を通じて、Google Cloudの活用事例が紹介されました</li>
</ul>
<p>▼東京ビッグサイト<br><img fetchpriority="high" src="/images/2025/20250826a/IMG_5382.jpg" alt="IMG_5382.jpg" width="1200" height="1210"></p>
<p>▼セッション会場<br><img src="/images/2025/20250826a/IMG_5442.jpg" alt="IMG_5442.jpg" width="1200" height="900" loading="lazy"></p>
<p>▼EXPO会場<br><img src="/images/2025/20250826a/IMG_5414.jpg" alt="IMG_5414.jpg" width="1200" height="900" loading="lazy"></p>
<h2 id="AI時代に我々に求められることは？">AI時代に我々に求められることは？</h2><p>今回のイベントを通じて、AIは単なる業務効率化ツールではなく、<strong>ビジネスモデルそのものを変革するもの</strong>であると感じました。多くの企業が当たり前のようにAIを使いこなす時代に、ITコンサルタントとして、私たちはどのような価値を創造できるかが問われています。AIを強力な武器とし、顧客の価値を高めていくことが、今後求められることだと考えます。</p>
<h2 id="Google-Cloud製品を使った最近のトレンド">Google Cloud製品を使った最近のトレンド</h2><p>今回のイベントで特に印象的だったのは、Vertex AIをはじめとするサービスが、企業の経営戦略課題を解決するための核となっていることです。多くのセッションやEXPOブースで、AIを業務に組み込む具体的な事例が紹介されていました。特に、以下のような活用がトレンドになりつつあると感じます。</p>
<ul>
<li><strong>企業内データの活用と活用基盤の構築</strong>: BigQueryやLooker studioなどのサービスを組み合わせて、データ収集からモデル学習やシミュレーション、ダッシュボードでの可視化までを一貫して行うワークフローが紹介されていました。これにより、データ活用のサイロ化を防ぎ、全社的なAI導入を加速させることが可能になります。企業の今後のAI活用としては、自社のデータをAIに学習・活用させ、いかにして経営戦略に反映させるかがカギになってきます。</li>
</ul>
<h2 id="進化を続けるAIエージェント">進化を続けるAIエージェント</h2><p>今回のイベントで最も注目すべきテーマの1つが、AIエージェントでした。自律的にタスクを完了させるAIエージェントの可能性に注目が集まっていました。</p>
<ul>
<li>概要<ul>
<li>AIエージェントは、ユーザーに代わって目標を達成し、タスクを完了するためにAIを活用するソフトウェアです。推論、計画、記憶、学習、適応能力を備え、自律的に意思決定を行います。また、テキスト、音声、動画などマルチモーダルな情報を処理したり、他のエージェントと連携して複雑なワークフローの調整・実行が可能です</li>
</ul>
</li>
<li>AIエージェントの主な機能<ul>
<li><strong>推論</strong>: 論理と利用可能な情報に基づいて結論を導き出し、問題を解決します</li>
<li><strong>行動</strong>: 意思決定や計画に基づいて、物理的またはデジタルな行動を起こします</li>
<li><strong>観察</strong>: コンピュータビジョンや自然言語処理を通じて、環境や状況に関する情報を収集します</li>
<li><strong>計画</strong>: 目標達成のための戦略を立て、最適な行動方針を選択します</li>
<li><strong>コラボレーション</strong>: 人間や他のAIエージェントと協力し、共通の目標を達成します</li>
<li><strong>自己改善</strong>: 経験から学び、フィードバックに基づいて動作を調整し、パフォーマンスを向上させます</li>
</ul>
</li>
</ul>
<h3 id="構成">構成</h3><p>AIエージェントの仕組みは、以下の構成要素によって成り立っています。</p>
<ul>
<li><strong>ペルソナ</strong>: エージェントの役割、個性、コミュニケーションスタイルを定義し、一貫したキャラクターを維持します</li>
<li><strong>メモリー</strong>: 短期記憶、長期記憶、エピソード記憶、コンセンサス記憶を備え、過去のやり取りから新しい状況に適応します</li>
<li><strong>ツール</strong>: エージェントが環境とやり取りし、機能を強化するために利用できる外部リソースや関数です</li>
<li><strong>モデル</strong>: 大規模言語モデル（LLM）がエージェントの「頭脳」として機能し、言語の処理と生成を可能にします</li>
</ul>
<p>セッションでは、AIエージェントが顧客からの問い合わせを分析し、適切な担当者にエスカレーションするデモが披露されていました。</p>
<p>AIエージェントは、新たなビジネスモデルやサービスを生み出す可能性を秘めています。今後、AIエージェントが私たちの働き方や顧客との接し方を大きく変えていくことは間違いありません。</p>
<h2 id="さいごに">さいごに</h2><p>Google Cloud Next Tokyo’25に参加し、AIの進化の速さを肌で感じることができました。日々新しい技術をキャッチアップし、AIを使いこなす側になることで、顧客への提供価値を高めていきたいです。</p>
<p>各セッションや基調講演のアーカイブは公式サイトにて、公開中です。</p>
<p>2026年も参加します！</p>
]]></content>
    <summary type="html">2025年8月5日に開催されたGoogle Cloud Next Tokyo'25に参加してきましたので、当日の様子をレポートします！</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="AIエージェント" scheme="https://future-architect.github.io/tags/AI%E3%82%A8%E3%83%BC%E3%82%B8%E3%82%A7%E3%83%B3%E3%83%88/"/>
    <category term="GoogleCloud" scheme="https://future-architect.github.io/tags/GoogleCloud/"/>
    <category term="GoogleCloudNext" scheme="https://future-architect.github.io/tags/GoogleCloudNext/"/>
    <category term="GoogleCloudNext2025" scheme="https://future-architect.github.io/tags/GoogleCloudNext2025/"/>
    <category term="参加レポート" scheme="https://future-architect.github.io/tags/%E5%8F%82%E5%8A%A0%E3%83%AC%E3%83%9D%E3%83%BC%E3%83%88/"/>
    <category term="生成AI" scheme="https://future-architect.github.io/tags/%E7%94%9F%E6%88%90AI/"/>
  </entry>
  <entry>
    <title>Cloud Composer (Apache Airflow) 実用インフラTips</title>
    <link href="https://future-architect.github.io/articles/20250206a/"/>
    <id>https://future-architect.github.io/articles/20250206a/</id>
    <published>2025-02-05T15:00:00.000Z</published>
    <updated>2025-02-05T15:00:00.000Z</updated>
    <author><name>岸下優介</name></author>
    <content type="html"><![CDATA[<img fetchpriority="high" src="/images/2025/20250206a/image.png" alt="" width="1200" height="447">

<h2 id="はじめに">はじめに</h2><p>Apache Airflowはワークフロー管理サービスで、スケジュールされた時間に一連の処理を行ってくれる便利なサービスです。ただ、運用には結構コストがかかるサービスです。</p>
<p>そのため、Google CloudではCloud Composer、AWSではAmazon Managed Workflows for Apache Airflow (Amazon MWAA)といった運用を楽にするためのマネージドなサービスが展開されています。</p>
<p>とは言え、マネージドなAirflowでさえも運用は難しく、色々な問題が起こりがちです。Cloud Composer自体、v1から始まり既にv3へと進化<sup id="fnref:1">1</sup>を遂げていることから、提供するGoogle側でも試行錯誤と努力の過程が見え透けてきます。</p>
<p>そこで本記事では、Cloud Composerを運用するプロジェクトにインフラ担当として2年ほど関わっきた中で経験的に得られたTipsを紹介します<sup id="fnref:2">2</sup>。</p>
<p>※本記事のTipsはCloud Composer v2をベースに話をしています。Airflow単体で当てはまる部分が多いとは思いますが、Cloud Composer v1やv3、Amazon MWAAでは一部当てはまらない可能性があることを考慮して読んで頂ける幸いです。</p>
<h2 id="Airflowのお約束事">Airflowのお約束事</h2><p>Airflowにてワークフローを記述するDirected Acyclic Graph（DAG）は<strong>決定的でべき等</strong>でなければなりません。<br>以下の記事に詳しく説明があります。</p>
<p>https://cloud.google.com/blog/ja/products/data-analytics/optimize-cloud-composer-via-better-airflow-dags</p>
<ul>
<li>決定的：特定の入力によって常に同じ出力が生成される必要</li>
<li>べき等：DAG を何度トリガーしても、毎回同じ効果 &#x2F; 結果が得られなければならない</li>
</ul>
<p>Cloud Composerを運用してる中でDAGとして定義されたワークフローのタスクは結構よくわからないタイミングで失敗します。原因は内部的なネットワーク上の問題だったり、データベースへのアクセス過多だったり、どうしようもない場合がよくあります。</p>
<p>AirflowのDAGでは標準でリトライ機能が搭載されているので、<strong>いつでもリトライを実施できるようにしておく</strong>ためにも、決定的でべき等なDAGを定義しておくことが大切です。</p>
<h2 id="ベストプラクティス回り">ベストプラクティス回り</h2><p>Airflowの公式ページにてベストプラクティスが公開されています。</p>
<p>https://airflow.apache.org/docs/apache-airflow/stable/best-practices.html</p>
<p>このべスプラ、結構大事なことが書いてあるのですが見落とされがちです。運用する中でどうしても守ってほしい2点についてここで紹介致します。</p>
<h3 id="Python-Codeにおけるトップレベルでの処理">Python Codeにおけるトップレベルでの処理</h3><p>https://airflow.apache.org/docs/apache-airflow/stable/best-practices.html#top-level-python-code</p>
<p>書いてある通りなのですが、DAGを構成するPythonファイルのトップレベルで無意味な重い処理を書かないようにしましょう。</p>
<p>特に見落としがちなのが、<code>import</code>処理に関しても同様なので注意が必要です。以下のように<code>tensorflow</code>や<code>torch</code>など<strong>Loadに時間のかかるライブラリ</strong>はBad exampleの様なimportは避けて、Good exampleの様にタスク関数内で呼び出すのがべスプラになります。</p>
<figure class="highlight python"><figcaption><span>Bad example</span></figcaption><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> random</span><br><span class="line"><span class="keyword">import</span> pendulum</span><br><span class="line"><span class="keyword">import</span> pandas <span class="comment"># Bad example</span></span><br><span class="line"><span class="keyword">import</span> torch <span class="comment"># Bad example</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">with</span> DAG(</span><br><span class="line">    dag_id=<span class="string">&quot;example_python_operator&quot;</span>,</span><br><span class="line">    schedule=<span class="literal">None</span>,</span><br><span class="line"><span class="comment"># ...</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@task()</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">do_stuff_with_pandas_and_torch</span>():</span><br><span class="line"><span class="comment"># ...</span></span><br></pre></td></tr></table></figure>

<figure class="highlight python"><figcaption><span>Good example</span></figcaption><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> random</span><br><span class="line"><span class="keyword">import</span> pendulum</span><br><span class="line"></span><br><span class="line"><span class="keyword">with</span> DAG(</span><br><span class="line">    dag_id=<span class="string">&quot;example_python_operator&quot;</span>,</span><br><span class="line">    schedule=<span class="literal">None</span>,</span><br><span class="line"><span class="comment"># ...</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@task()</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">do_stuff_with_pandas_and_torch</span>():</span><br><span class="line">    <span class="keyword">import</span> pandas <span class="comment"># Good example</span></span><br><span class="line">    <span class="keyword">import</span> torch <span class="comment"># Good example</span></span><br><span class="line"><span class="comment"># ...</span></span><br></pre></td></tr></table></figure>

<p>なぜこれが良くないかと言うと、Airflowでは各DAGを管理し、時間通りに実行できるようにスケジュールする管理役のSchedulerコンテナが存在しており、このコンテナが定期的にデプロイ済みのPythonファイルを実行可能かどうかを解析しています。そのため、トップレベルに重い処理があると解析時間が伸びてしまい、ワークフローのスケジュールに影響を及ぼしてしまいます。</p>
<blockquote>
<p>Airflow scheduler executes the code outside the Operator’s execute methods with the minimum interval of min_file_process_interval seconds. This is done in order to allow dynamic scheduling of the DAGs - where scheduling and dependencies might change over time and impact the next schedule of the DAG. Airflow scheduler tries to continuously make sure that what you have in DAGs is correctly reflected in scheduled tasks.</p>
</blockquote>
<h3 id="Airflow-Variablesの呼び出し">Airflow Variablesの呼び出し</h3><p>https://airflow.apache.org/docs/apache-airflow/stable/best-practices.html#airflow-variables</p>
<p>こちらも前章と似たような内容ですが、トップレベルでAirflow Variablesの呼び出しはできるだけ少なくしましょう。理由としては、ネットワーク上の呼び出しやデータベースへのアクセス処理が伴うため、こちらもスケジューラの定期的な解析処理に影響を及ぼします。</p>
<blockquote>
<p>Using Airflow Variables yields network calls and database access, so their usage in top-level Python code for DAGs should be avoided as much as possible, as mentioned in the previous chapter, Top level Python Code.</p>
</blockquote>
<h2 id="コマンド回り">コマンド回り</h2><h3 id="デプロイにはgcloud-storage-rsyncを使う">デプロイにはgcloud storage rsyncを使う</h3><p>Cloud ComposerにDAGをデプロイするには、環境が指定するGCS Bucketへファイルを配置する必要がありますが、いちいち手動でやっていると事故ることが多いです。そこで、GitHubやGitLabなどの本番用ブランチをSingle Source of TruthとしてJenkins、GitHub Actions、GitLab CIなどでデプロイ用のJobを用意すると思います。その際、<code>gcloud storage cp</code>でDAGをコピーするよりも<code>gcloud storage rsync</code>がお勧めです。</p>
<p>https://cloud.google.com/sdk/gcloud/reference/storage/rsync</p>
<p>理由としては<code>gcloud storage rsync</code>はコピー元を正として、コピー先を同じ状態にします。そのため、本番ブランチから削除されたDAGのPythonファイルは削除され、運用中のDAGのみがディレクトリへ残ることになります。</p>
<p>もちろんDAG内で<code>schedule_interval</code>を<code>None</code>にすることでも無効化はできますが、常にAirflowの環境に運用中のワークフローのみを置きたい場合はこれできれいな状態を保つことができます。</p>
<h3 id="Airflow-CLIを使う">Airflow CLIを使う</h3><p>AirflowにはCLIが用意されており、例えばAirflow UI内での操作権限を制御（<code>Admin</code>や<code>Op</code>の付与）するためにコマンド操作が必要となります。これらのコマンド操作は<code>gcloud</code>コマンド経由でAirflowのCLIにアクセスできます。</p>
<p>https://cloud.google.com/composer/docs/composer-2/access-airflow-cli?hl=ja</p>
<p>https://cloud.google.com/composer/docs/composer-2/airflow-rbac?hl=ja</p>
<h2 id="リソース周り">リソース周り</h2><p>Cloud Composerは結構お金のかかるサービスなので、初期構築時にリソースをできるだけ抑えたくなります。ただ、抑えすぎるとAirflowが処理し切れなくなり、スケジュールされていたが実行されなかったゾンビタスクと呼ばれるエラーが発生します。</p>
<blockquote>
<p>ゾンビタスクは、実行されるはずであるが実行されていないタスクです。これは、タスクのプロセスが終了済みか応答していない場合、Airflow ワーカーが過負荷のためにタスク ステータスを時間内に報告しなかった場合、またはタスクが実行された VM がシャットダウンされた場合に発生します。Airflow はそのようなタスクを定期的に検出し、タスクの設定に応じて、失敗するか、再試行します。</p>
</blockquote>
<p>https://cloud.google.com/composer/docs/composer-2/troubleshooting-dags?hl=ja#zombie-tasks</p>
<p>自分もゾンビタスクには散々苦しめられましたので、その中で得られたTipsを紹介します。</p>
<h3 id="WorkerやSchedulerの初期値">WorkerやSchedulerの初期値</h3><p>Cloud Composer環境を構築する際、WorkerやSchedulerのCPUコア数やメモリを予め決める必要があります（もちろん、後から変更できます）。<br>その場合、実装予定のDAGの数をある程度想定し、それらDAGを並列に実行したい数やタスクを並列に実行したい数から以下のように逆算できます。</p>
<img src="/images/2025/20250206a/Screen_Shot_2020-02-04_at_3.36.36_PM.max-1400x1400.png" alt="Screen_Shot_2020-02-04_at_3.36.36_PM.max-1400x1400.png" width="1200" height="1339" loading="lazy">

<p>Airflowの各パラメータの決め方<br>画像引用元：https://cloud.google.com/blog/ja/products/data-analytics/scale-your-composer-environment-together-your-business</p>
<h3 id="Schedulerのリソース侮るなかれ">Schedulerのリソース侮るなかれ</h3><img src="/images/2025/20250206a/image_2.png" alt="image.png" width="1200" height="436" loading="lazy">

<p>Schedulerのリソース使用状況<br>画像引用元: https://cloud.google.com/composer/docs/composer-2/optimize-environments?hl=ja</p>
<p>ゾンビタスクが発生した際、ワークフローを実行する主体であるWorkerに関してはCPUやメモリの使用率に対して感度高く見るかと思います。もちろんWorkerのリソース不足に起因する場合が多いのですが、ワークフローのまとめ役であるSchedulerが起因している場合もあるので、CPUやメモリの使用率が高くなっていないか気を配ってあげてください。SchedulerのCPU使用率が常に上限に張り付いてしまい、DAGが予定通りスケジュールされなかった！みたいなケースを何度か見てきました。</p>
<p>もしお金に余裕がある場合は、SchedulerのPodを2台構成にするのもおススメです。予測できないタイミングでSchedulerの再起動（クラッシュ？）が発生し、1台構成がゆえにスケジューリングに失敗してしまったというパターンもありました。</p>
<h3 id="Airflowデータベースのクリーンアップを導入する">Airflowデータベースのクリーンアップを導入する</h3><p>実運用の中でAirflowデータベースへのアクセスが発生しないので見落とされがちなのですが、Airflowでは時間の経過とともに環境のAirflowデータベースに保存されるデータが増えていきます。蓄積されるデータは過去のDAG実行やタスクなどオペレーションに関連する情報で、ほとんどのケースで恒久的に必要となる情報ではありません。<br>そしてドキュメントには以下のように記載されており、データベースのストレージはなるべく圧迫しないようにしておく必要があるようです。</p>
<blockquote>
<ul>
<li>Airflow データベースのサイズが 16 GB を超える場合、環境を新しいバージョンにアップグレードすることはできません。</li>
<li>Airflow データベースのサイズが 20 GB を超える場合、スナップショットを作成することはできません。</li>
</ul>
</blockquote>
<p>また、これはサポートケースへの問い合わせの中でご教示頂いたのですが、データベースクリーンアップが<strong>ゾンビタスク撲滅にある程度の効果を発揮する</strong>とのことでした。<br>導入方法は以下で紹介されており、基本的にコピペしてデプロイするだけなので是非導入してみてください。</p>
<p>https://cloud.google.com/composer/docs/composer-2/cleanup-airflow-database?hl=ja</p>
<h3 id="dataにはなるべくファイル放置しない"><code>/data</code>にはなるべくファイル放置しない</h3><p>タスクが生成して使用するデータを保存するのにCloud Composer環境のGCS Bucketには<code>data</code>というディレクトリが存在します。</p>
<p>https://cloud.google.com/composer/docs/composer-2/cloud-storage?hl=ja#folders_in_the_bucket</p>
<p>Cloud Composerの全体アーキを見るとわかるのですが、このGCS BucketはGCS Fuseを介してSchedulerやWorkerのPodに中身が同期される仕組みとなっております。</p>
<img src="/images/2025/20250206a/image_3.png" alt="image.png" width="1200" height="1297" loading="lazy">

<p>プライベートIP環境のアーキテクチャ<br>画像引用元：https://cloud.google.com/composer/docs/composer-2/environment-architecture?hl=ja</p>
<p><code>/data</code>配下に関してもGCS FuseによってSchedulerやWorkerのPodへ同期される仕組みとなっており、過去に生成したファイルが大量に<code>/data</code>配下に残っていると同期のパフォーマンスに影響を及ぼす可能性があります。実際にGCS Fuseが大暴れして障害に発展したパターンも遭遇しました。</p>
<p><code>/data</code>に配置したファイルは用が済み次第、削除するように心がけましょう。</p>
<h2 id="まとめ">まとめ</h2><p>Cloud ComposerもといApache Airflowを運用する中で得られたTipsを主にインフラの観点で紹介しました。</p>
<p>これらのTipsがAirflow運用者の一助になれば幸いです。</p>
<p>アイキャッチ画像はGoogle Cloud公式ページ、Apache Airflow公式ページからの引用させて頂きました。</p>
<div id="footnotes"><hr><div id="footnotelist"><ol style="list-style:none; padding-left: 0;"><li id="fn:1"><span style="vertical-align: top; padding-right: 10px;">1.</span><span style="vertical-align: top;">v1からv2へ去年移行したばっかりなのに...</span> ↩</li><li id="fn:2"><span style="vertical-align: top; padding-right: 10px;">2.</span><span style="vertical-align: top;">最近は比較的に安定して運用できてる感は出てきましたが、まだまだ発展途上な部分は多いというのが現実です。</span> ↩</li></ol></div></div>]]></content>
    <summary type="html">Apache Airflowはワークフロー管理サービスで、スケジュールされた時間に一連の処理を行ってくれる便利なサービスです。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="Airflow" scheme="https://future-architect.github.io/tags/Airflow/"/>
    <category term="GoogleCloud" scheme="https://future-architect.github.io/tags/GoogleCloud/"/>
    <category term="Tips" scheme="https://future-architect.github.io/tags/Tips/"/>
  </entry>
  <entry>
    <title>Google Cloud 資格試験 全冠体験記</title>
    <link href="https://future-architect.github.io/articles/20241101a/"/>
    <id>https://future-architect.github.io/articles/20241101a/</id>
    <published>2024-10-31T15:00:00.000Z</published>
    <updated>2024-10-31T15:00:00.000Z</updated>
    <author><name>逆瀬川滉大</name></author>
    <content type="html"><![CDATA[<h2 id="はじめに">はじめに</h2><p>TIG(Technology Innovation Group) 所属、逆瀬川です。</p>
<p>Google Cloud 資格試験の全冠が完了しましたという、体験記です。</p>
<p>こちらに記載のある11個の資格を受験し、合格しました。</p>
<p>https://cloud.google.com/learn/certification?hl=en</p>
<h2 id="受験期間">受験期間</h2><ul>
<li>2023&#x2F;7-2024&#x2F;7</li>
</ul>
<h2 id="対象試験">対象試験</h2><ul>
<li>Cloud Digital Leader</li>
<li>Associate Cloud Engineer</li>
<li>Professional Cloud Architect</li>
<li>Professional Cloud Database Engineer</li>
<li>Professional Cloud Developer</li>
<li>Professional Data Engineer</li>
<li>Professional Cloud DevOps Engineer</li>
<li>Professional Cloud Security Engineer</li>
<li>Professional Cloud Network Engineer</li>
<li>Professional Google Workspace Administrator</li>
<li>Professional Machine Learning Engineer</li>
</ul>
<p>なお、ありがたいことに、社内の方がいずれの試験もブログを書いて下さっています。<br>各試験について知りたい方は、ご参照ください。</p>
<div class="scroll"><table>
<thead>
<tr>
<th>Certification</th>
<th>Future社員の合格体験記</th>
</tr>
</thead>
<tbody><tr>
<td>Cloud Digital Leader</td>
<td>https://future-architect.github.io/articles/20231226a/</td>
</tr>
<tr>
<td>Associate Cloud Engineer</td>
<td>https://future-architect.github.io/articles/20210625a/</td>
</tr>
<tr>
<td>Professional Cloud Architect</td>
<td>https://future-architect.github.io/articles/20190530/ <br> https://future-architect.github.io/articles/20220411a/</td>
</tr>
<tr>
<td>Professional Cloud Database Engineer</td>
<td>https://future-architect.github.io/articles/20240730a/</td>
</tr>
<tr>
<td>Professional Cloud Developer</td>
<td>https://future-architect.github.io/articles/20240117a/</td>
</tr>
<tr>
<td>Professional Data Engineer</td>
<td>https://future-architect.github.io/articles/20211013a/ <br> https://future-architect.github.io/articles/20230915a/</td>
</tr>
<tr>
<td>Professional Cloud DevOps Engineer</td>
<td>https://future-architect.github.io/articles/20240731a/</td>
</tr>
<tr>
<td>Professional Cloud Security Engineer</td>
<td>https://future-architect.github.io/articles/20230921a/</td>
</tr>
<tr>
<td>Professional Cloud Network Engineer</td>
<td>https://future-architect.github.io/articles/20200902/</td>
</tr>
<tr>
<td>Professional Google Workspace Administrator</td>
<td>https://future-architect.github.io/articles/20240801a/</td>
</tr>
<tr>
<td>Professional Machine Learning Engineer</td>
<td>https://future-architect.github.io/articles/20220930a/</td>
</tr>
</tbody></table></div>
<h2 id="筆者の前提知識">筆者の前提知識</h2><p>Google Cloudに関連する経験として、以下がありました。</p>
<ul>
<li>アプリ側チーム（Google Cloud上で動くシステムの開発）にて1.5年ほど<ul>
<li>Google Cloud に直接触るタスクはなかったですが、覗ける範囲で色々見たり、アーキ図書き起こして答え合わせしてみたり、などしてました</li>
</ul>
</li>
<li>インフラ側チーム にて2年ほど<ul>
<li>組織全体のGoogle Cloudプロジェクトを包括的に見る業務に携わっています</li>
<li>こちらは 毎日 Google Cloud に触ります</li>
</ul>
</li>
</ul>
<h2 id="勉強方法">勉強方法</h2><p>普段の業務でGoogle Cloud を毎日触ってるため、とりあえず模擬試験を受け、足りない箇所を補強するスタイルで進めていました。</p>
<ol>
<li>模擬試験①： 公式で無料公開されているものを受ける</li>
<li>模擬試験②： Udemyで出ている模擬試験を購入して、追加で補強する</li>
<li>公式ドキュメント： 模擬試験で知識薄いと感じた部分は、公式ドキュメントを読み直す</li>
<li>手を動かす： 親しみがあまりないサービスについては、追加で手を動かして触ってみる</li>
</ol>
<p>また、模擬試験の問題を解く際に紙とペンを用意して、その問題のアーキ図を書き起こす、というのをずっとやってましたが、理解を捗らせる点で良かったように思います。</p>
<p>あと、試験を受けるのは日曜8時からで固定していました。<br>いつ受けようかなの選択肢を減らした方が、リズムもできてスムーズに進んだように思います。</p>
<h2 id="各試験の所感">各試験の所感</h2><p>簡単にですが、1周してみての所感です。</p>
<ul>
<li>やはり、Professional Cloud Architect が中心にあり、その色んな方向の延長線上に他Professional 系がある</li>
<li>Professional Machine Learning Engineer、Professional Cloud Network Engineer はしっかり準備しないと問題文が長いのもあって、割と時間が押される印象<ul>
<li>特にMLは英語なので慣れていないと問題文読むのに時間かかる</li>
</ul>
</li>
<li>Professional Google Workspace Administratorが若干斜めに外れた位置にあった印象<ul>
<li>純粋にGoogle Cloudだけで、その際GWSに触れていない方は、とっかかりに時間かかるかも</li>
</ul>
</li>
<li>Professional Cloud Database Engineer、Professional Machine Learning Engineerは今のところ日本語非対応で英語なので、そこは頑張る<ul>
<li>英語としては、公式ドキュメントに普段出てくる程度の単語レベルだが、英語を読み慣れてないと読解自体に時間かかる</li>
</ul>
</li>
</ul>
<h2 id="受験・合格するメリット">受験・合格するメリット</h2><p>勿論、資格が残るのはありますが、その他で以下があったように思います。</p>
<h3 id="1-自身の知識の濃淡がわかる、知識欲が増す">1. 自身の知識の濃淡がわかる、知識欲が増す</h3><p>1周すべて受けることで、どのあたりの知識は豊富でどのあたりの知識が少ないのかよくわかりました。</p>
<p>業務で触れていた部分の知識が多くなるのはわかるのですが、全体の中でどの部分の知識が少ないのかわかるのはよかったと思います。</p>
<p>知識の少ないところがわかるとそこを潰したくなり、結果、知識欲がさらに増すという点でも、メリットがあったように思います。</p>
<h3 id="2-リリースノートが読みやすくなる">2. リリースノートが読みやすくなる</h3><p>サービスアップデートに追随するため、チーム内で毎日リリースノートを読むようにしています。</p>
<p>この際によく知らないサービスの、よく知らないアップデート だと（わからない）× （わからない）でリリースノートを読むハードルが上がるように思います。</p>
<p>勿論、使っていないサービスのアップデートはある程度読み飛ばしても困らないとは思います。ただ、その場合は自分たちの使っているサービス内に知識が留まり、選択肢が増えていかないので、長期的に見るとよろしくはないかなと。</p>
<p>全冠して1周したことで、よく知らない（見たことない）サービス、の方は減ったので、その点で、リリースノートは全体的に読みやすくなったと感じました。</p>
<p>https://cloud.google.com/release-notes</p>
<h3 id="3-他の人が試験を受けるきっかけを作りやすくなる">3. 他の人が試験を受けるきっかけを作りやすくなる</h3><p>当たり前ですが、知識量の多い人間が1人いるより、チーム全体としての知識が厚い方が強いです（前者だと、その人が依存点になってしまうので）。</p>
<p>現在、チームを運営する立場にあり、チームの知識量を増やす手段の一つとして、資格試験を活用できないか考えていました。以下のようなやり方も取れるようです。</p>
<figure class="highlight txt"><table><tr><td class="code"><pre><span class="line">1. チーム内のメンバーの方が、業務で何かハマりどころに出会う・解決する</span><br><span class="line">2. ちなみに今回業務に出たこの問題・課題はこの試験範囲にあるもの、というのをお伝えする</span><br><span class="line">（実際にいずれ試験も受けたことがあるので、どの試験に出てくる話かはわかる）</span><br><span class="line">3. 周辺知識の勉強もかねて、試験受けてみたらどうですかね？というのをお伝えしてみる</span><br></pre></td></tr></table></figure>

<p>例：</p>
<ul>
<li>アラートで使われていたError Budgetの理解に時間がかかった → Professional Cloud DevOps Engineer で見かけるやつなので、周辺知識習得もかねて受けてみては？</li>
<li>VPC推移的peeringできない問題でハマった → peering, Cloud VPN, Cloud Interconnect の使い分け辺りも含めてProfessional Cloud Network Engineer 解いてみてもよいかもです（推移的peeringできないと知っているだけで解ける問題もある）</li>
</ul>
<p>…などなど。</p>
<p>この流れで、チーム内のメンバーの方が、後日「合格してました」と言って帰ってきた事例がいくつかありました。フックがあった方が、資格試験も受けやすいというのはあるようです（なお、無料バウチャーが一番強い動機だった気はします）。</p>
<p>何もないところから、試験のためだけの勉強は、人によってはモチベーションが維持しにくいと思います。一方で、普段の業務と紐づけがされると、やったことがある、見たことがあるものなので受験のハードルは下がりやすいです。そして、一度通ったことがある人の方がその紐づけの線は引きやすいのかなと。</p>
<p>あとは、これでチーム内の資格保有者が増えると、2のチーム内リリースノート読みもさらにしやすくなります。</p>
<p>チーム内の知識を増やすきっかけ・導線 を作れる、というメリットもあるように思います。</p>
<h3 id="4-特典">4. 特典</h3><p>毎年あるのかわからないですが、特典がありました。</p>
<p>Google Cloud Next Tokyo 2024 に行った際、全冠特典でマグカップを頂きました。<br>（転倒防止に、垂直に持ち上げないと接地面から離れにくい作りになっているようです。すごい）</p>
<p>https://cloudonair.withgoogle.com/events/next-tokyo-24</p>
<img fetchpriority="high" src="/images/2024/20241101a/IMG20241025073005.jpg" alt="Google Cloudのログが付いたマグカップ" width="1200" height="900">

<h2 id="おわりに">おわりに</h2><p>以上です。</p>
<p>最後まで読んでいただき、ありがとうございました。</p>
]]></content>
    <summary type="html">Google Cloud 資格試験の全冠が完了したので、体験記の記載です</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="GoogleCloud" scheme="https://future-architect.github.io/tags/GoogleCloud/"/>
    <category term="全冠" scheme="https://future-architect.github.io/tags/%E5%85%A8%E5%86%A0/"/>
    <category term="合格記" scheme="https://future-architect.github.io/tags/%E5%90%88%E6%A0%BC%E8%A8%98/"/>
  </entry>
  <entry>
    <title>Google Cloud Next Tokyo '24 2日目参加レポート</title>
    <link href="https://future-architect.github.io/articles/20240805a/"/>
    <id>https://future-architect.github.io/articles/20240805a/</id>
    <published>2024-08-04T15:00:00.000Z</published>
    <updated>2024-08-04T15:00:00.000Z</updated>
    <author><name>岸下優介</name></author>
    <content type="html"><![CDATA[<img fetchpriority="high" src="/images/2024/20240805a/image.png" alt="" width="1200" height="542">

<h2 id="はじめに">はじめに</h2><p>2024年 8&#x2F;1-8&#x2F;2 にパシフィコ横浜で開催されているGoogle Cloud Next Tokyo ‘24に同じプロジェクトのメンバー数名で参加してきました。</p>
<p>この記事はDay2（8&#x2F;2）の参加レポートです。</p>
<p>Day1のレポートはGoogle Cloud Next Tokyo ‘24 1日目参加レポートです。</p>
<h2 id="基調講演">基調講演</h2><p>Day1と比較すると企業でのGoogle Cloud、主にGeminiの活用事例の話がメインでしたが、Day1に引き続き「生成AIを試す時代から実用化する時代への変化」というテーマが感じられる基調講演でした。活用事例としては以下が紹介されていました。</p>
<ul>
<li>日本テレビ放送網さんにおけるGeminiを活用した動画像解析</li>
<li>ヤマト運輸さんにおけるGoogle Maps Platformを活用した配送計画</li>
<li>トヨタ自動車様における現場での利用を目指したAIプラットフォーム構築でのGemini Code Assistの活用</li>
<li>三井住友フィナンシャルグループ様におけるIT活用戦略とOffice365とGoogle Workspaceのハイブリッド利用</li>
</ul>
<p>また、基調講演内で発表されたGoogle Cloudのアップデートとしては以下がありました。</p>
<ul>
<li>Data Preparation for Gemini in BigQuery</li>
<li>Vector Indexing in BigQuery</li>
<li>BigQuery to Vertex AI</li>
<li>Gemini in Looker</li>
<li>Spanner Graph</li>
<li>Spannerに全文検索とベクトル検索が追加</li>
<li>Spanner Edition</li>
<li>BigtableにおけるSQLサポート</li>
</ul>
<p>特にSpannerは今回のアップデートによって益々使いやすいものとなりそうです。</p>
<h2 id="セッション講演">セッション講演</h2><p>Day2では5つのセッション講演を聞くことができました。ざっくりとした中身と所感を書いていきます。</p>
<h3 id="建築・建設業界の-DX-化を加速させるアンドパッドの-AI-LLM-活用事例（株式会社アンドパッド）">建築・建設業界の DX 化を加速させるアンドパッドの AI &#x2F; LLM 活用事例（株式会社アンドパッド）</h3><ul>
<li>建築・建設業界の上流から下流までを一元管理できるアプリ開発</li>
<li>作業現場情報を残す手段として黒板に書き込み、写真を撮って残すのが通例<ul>
<li>この部分のデジタル化・自動化を目指すべく豆図AIキャプチャと黒板AIにおけるAI・LLM活用事例の紹介</li>
<li>ちなみに豆図は工事写真を補足説明するための断面の模式図や写真</li>
</ul>
</li>
<li>取り扱うデータに非構造データが多い<ul>
<li>図面、ドキュメント、現場写真、チャットなど</li>
<li>業界ならではの特殊記号が多い</li>
<li>データの取り込みにOCRが主流だったが、LLM（Gemini）の活用を進めている</li>
</ul>
</li>
<li>OCRとGeminiの比較<ul>
<li>それぞれチューニングしたうえで認識結果を比較したところ、Geminiが圧勝</li>
<li>Geminiはfew-shot learningによって更なる性能向上の可能性が見られた</li>
<li>Geminiに対するリクエストコストと精度のバランスが大事<ul>
<li>図面全体をスキャンさせると精度は上がるが、お金もかかる</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>OCRとGeminiの比較の話が面白かったです。前職でOCRを少し触っていたこともあり、認識精度を高めようとすると要らない部分まで文字と認識されるなどOCRの苦しみを味わったことがあります。GeminiなどLLMによって、コンテキストを理解することで精度高く文字・記号認識ができるようになってきたのは革新的ですね。もちろんコストが全然違うので、LLMによってOCRがすぐに淘汰されるということはなく、OCRを使うかLLMを使うかのシチュエーションやコストバランスが大事だと思いました。</p>
<h3 id="引越にゃんこ大戦争ー運営中のゲームを-Google-Cloud-に移行するためにしたこと（ポノス株式会社）">引越にゃんこ大戦争ー運営中のゲームを Google Cloud に移行するためにしたこと（ポノス株式会社）</h3><ul>
<li>Aurora MySQLからSpannerへの移行話<ul>
<li>移行は現在進行形</li>
</ul>
</li>
<li>移行理由<ul>
<li>メンテナンスがつらい</li>
<li>SpannerでUpsertができるようになった</li>
<li>（他にもありましたが聞き逃しました）</li>
</ul>
</li>
<li>やめられない、止まらない<ul>
<li>移行はしたいがサービスは止められない</li>
<li>過去バージョンのアプリでも遊べるようにしておきたい</li>
<li>引っ越しサービスを考案<ul>
<li>希望ユーザー（アクティブユーザー）のみ、引っ越しサービス経由で移行してもらう<ul>
<li>Cloud VPN（AWS⇔Google Cloud）でAuroraに直接クエリを投げて移行</li>
</ul>
</li>
<li>非アクティブユーザーは後日に一括移行</li>
</ul>
</li>
</ul>
</li>
<li>負荷テスト話<ul>
<li>GKE+Locust</li>
<li>ボトルネックを探すのにはCloud Traceが超便利だった</li>
<li>Cloud Runで全く性能が出ずに胃が痛くなる日々<ul>
<li>パフォーマンスチューニングがされていないだけだった</li>
<li>AWSではElastic Beanstalkを使っていて、元々良い感じにチューニングされていた</li>
</ul>
</li>
</ul>
</li>
<li>サーバー切り替え話<ul>
<li>クライアント側の問題で、DNSを切り替えてもすぐに向き先が変わらない場合もある</li>
<li>AWS側で新ドメインを作っておき、リバースプロキシで対応</li>
</ul>
</li>
</ul>
<p>Google Cloudへの現在進行形な移行話を赤裸々に語っており、非常に勉強になるセッションでした。特に「引っ越しサービス」という形でアクティブユーザーのデータ移行を実現しており、サービス運営しながらユーザーに配慮した移行というアイデアの素晴らしさを感じました。</p>
<p>また、AuroraからSpannerへの移行話はDay1の「スケーラビリティと信頼性を追求: Global で 5,500 万ユーザーを抱えるカレンダー シェアアプリのデータベースを Aurora から Cloud Spanner へ移行」でも語られておりました。この発表でも、SpannerでUpsertができるようになったことが移行の障壁を下げたとの内容があり、今後も同様の移行話が出てきそうです。</p>
<p>ちなみに、負荷テスト話で出てきたGKE+Locustによる負荷テストは拙著もあるので参考にしてください。</p>
<ul>
<li>LocustとGKEでスケーラブルな負荷テスト</li>
</ul>
<h3 id="BNE-ゲームタイトルにおけるリリース前後のインフラの最適化と課題（株式会社バンダイナムコエンターテインメント）">BNE ゲームタイトルにおけるリリース前後のインフラの最適化と課題（株式会社バンダイナムコエンターテインメント）</h3><ul>
<li>2つのゲームタイトル事例を紹介<ul>
<li>僕のヒーローアカデミア ULTRA RUMBLE</li>
<li>鉄拳8</li>
</ul>
</li>
<li>構成<ul>
<li>GKE + Agones</li>
</ul>
</li>
<li>サーバーコスト圧縮<ul>
<li>サーバーをn1-standard-4→T2D-standard-4へ変更</li>
<li>1.8コアで1試合だったのが、0.8コアで1試合できるようになり、1サーバーで4試合対応可能に</li>
<li>サーバーのチップが変わってしまうのが大きな決断ではあったが、何とか対応できた</li>
</ul>
</li>
<li>ワールドワイドマッチング<ul>
<li>北米・欧州・アジア圏といったRegion区切りでGKEを配置</li>
<li>ゲームは物理的条件によるレイテンシが結構効いてくる<ul>
<li>例えばアジア圏といってもシンガポールから日本は結構距離があるため、P2Pが大変</li>
</ul>
</li>
</ul>
</li>
<li>開発におけるTIPS話<ul>
<li>設計段階でGKEの1Podに収容する人数を決めておく<ul>
<li>何CPU必要なのかといったインフラコストに直結するため</li>
<li>場合によってはAgonesを使わないほうが安上がりする場合もある</li>
</ul>
</li>
<li>通信量と通信料<ul>
<li>EGRESSの通信量が膨らみがち</li>
<li>EGRESSの通信料はComputeEngineの料金の中で課金されるので見逃さないように気を付けたい</li>
</ul>
</li>
<li>バッファとするPod数<ul>
<li>バッファは保険なのでコストがかかり続ける</li>
<li>結構ぎりぎりを攻めるようにしている</li>
</ul>
</li>
</ul>
</li>
<li>Spanner話<ul>
<li>プロファイリングの手段<ul>
<li>無知は罪</li>
<li>APM、Cloud Trace、Datadogなどプロファイリングするのはマスト</li>
</ul>
</li>
<li>ウォームアップ<ul>
<li>リリース前にノード数を増加するだけではリシャーディングされないため、負荷に耐えられなくなる</li>
<li>リリースの数日前には負荷テストを行ってウォームアップしておき、確実にリシャードしておく</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>個人的にゲームが好きなので、自分たちが触れる表側を想像しながらその裏側話を聞くのは大変楽しいものです。ゲーム内の衝突判定にはCloudのネットワークでは遅すぎるからP2Pを利用している部分や、マッチング毎にGKEのPodが立ち上がり、その中で試合が行われているなどワクワクする話が盛りだくさんです。</p>
<p>ゲームにおけるマルチリージョナル戦略は単純に可用性を高めるためというわけではなく、物理的にユーザーと距離を縮めておかないとレイテンシによってサービスが提供できないというあたりが業界の違いを感じさせられます。また、ゲームのマッチ毎にPodがポコポコ立ち上がり、終われば消滅していく部分などもGKEというかKubernetesの恩恵をフルに享受できているんだなーと思いました。</p>
<h3 id="Google-Cloud-を用いたソフトウェア開発の内製化組織の早期立ち上げの実現（株式会社EARTHBRAIN）">Google Cloud を用いたソフトウェア開発の内製化組織の早期立ち上げの実現（株式会社EARTHBRAIN）</h3><ul>
<li>内製化によってソフトウェアのコントローラビリティを獲得する<ul>
<li>ビジネス上必要なシステムの機能追加をしつづけられる</li>
<li>開発時間の短縮</li>
<li>専属の内製チームにノウハウを蓄積させる</li>
</ul>
</li>
<li>内製化組織に向けたポイント<ul>
<li>コア業務・技術を中心に内製化する<ul>
<li>例えば、EARTHBRAIN社ではDataplatformと3D技術</li>
<li>競争優位性を維持しやすい</li>
<li>隣接市場へ裾野を広げることも可能</li>
</ul>
</li>
<li>フルマネージドサービスの活用<ul>
<li>ノンコア業務は内製化しない</li>
<li>何をやるかと何をやらないのかを見極める</li>
</ul>
</li>
</ul>
</li>
<li>経営資源を効率よく投下すべき<ul>
<li>メリハリをつけた開発</li>
<li>昨今の国内エンジニアの採用は難しい…<ul>
<li>分野を絞ってエンジニアを集める</li>
<li>Internal Developer Platformはすぐに利益に直結しない<ul>
<li>やりたいけど、一旦我慢する</li>
</ul>
</li>
</ul>
</li>
<li>競争優位性に繋がる領域に絞って経営資源を投下する</li>
</ul>
</li>
<li>内製化後の改善も大切<ul>
<li>To-Be像とのギャップを埋めていく</li>
<li>DORAの4keysを活用しEliteを目指す</li>
<li>もちろん、それぞれの指標で改善の労力は全然違うので、何を優先すべきかを考える</li>
</ul>
</li>
</ul>
<p>内製化組織を作っていくにあたっての組織や経営の話をされており、一番ハッとさせられる発表でした。自分はエンジニアリング寄りの人間でソフトウェア開発において全てをコントローラブルにしたいという気持ちになりがちなため、<strong>何をやらないのかを見極める</strong>という観点はいつも忘れてるなーと痛感させられました。また、一概に内製化と言っても全て自分たちで作る必要はなく、他と比べて優位に立てる業務を見極めてそこから裾野を広げていくという考えは常に心に留めておきたいと思いました。</p>
<h3 id="データ分析環境の-Google-Cloud-移行（出前館）">データ分析環境の Google Cloud 移行（出前館）</h3><ul>
<li>出前館のDWH<ul>
<li>200TBのストレージ</li>
<li>9000のテーブル</li>
<li>9300億レコードと5億レコード&#x2F;dayの更新</li>
</ul>
</li>
<li>移行理由<ul>
<li>従来のデータ分析環境の限界<ul>
<li>2000年にスタートしたサービスでシステムがレガシー</li>
<li>SQLのレスポンスが遅すぎる</li>
<li>データ統合が不完全</li>
<li>Biz側の要求に応えるのに時間がかかる</li>
</ul>
</li>
<li>業界スタンダードな環境が必要<ul>
<li>取り扱いに知識が必要で採用に障害となっている</li>
</ul>
</li>
<li>タイミング<ul>
<li>他の基盤刷新もあり、同じタイミングで移行できた</li>
</ul>
</li>
</ul>
</li>
<li>移行後の構成<ul>
<li>DB→GCS→Composer（Airflow）</li>
</ul>
</li>
<li>運用話<ul>
<li>BigQueryのSlotを利用し、Slot数はCloud Functionで繁忙時間に合わせて動的に変更</li>
<li>データ連携の時間をダッシュボード化しSLAを決める</li>
<li>Dataprexを利用してデータカタログを作る</li>
</ul>
</li>
<li>移行後のいろいろ<ul>
<li>改善事例<ul>
<li>独自環境ではなくなったため、学習コストが劇的に下がった</li>
<li>粒度の高いデータ提供ができるようになった</li>
<li>マッチングアルゴリズムや待ち時間予測モデルなどの精度向上</li>
<li>配達員のUXが劇的に改善した</li>
</ul>
</li>
<li>課題<ul>
<li>データマネジメントの問題<ul>
<li>BizユーザーからDatamartやDWHそのものを扱いたいという要望</li>
<li>想定していないユースケースだったため、データがマネジメントされていない</li>
<li>DMBOK2に基づいて問題の整理や改善中</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>自分も現在のプロジェクトではデータ分析基盤に関わっていることもあり、非常に学びになりました。特にBigQueryのSlotは昨年のEditionの導入によって料金が上がってしまったので、動的にSlot数を制御するのは有用だなーと感じました。また、Bizユーザーが自身で直接DWHを利用したりDatamartを構築したりといった需要は、自身のプロジェクトを鑑みてもかなり高まってきてる感は共感できました。BigQueryなどでデータが簡単に扱えるようになったこともあり、更にデータの民主化が進んでいきそうです。</p>
<p>ちなみに、9月上旬ごろにはセッションの動画もYouTube等で公開されるみたいなので、ぜひ気になる講演があれば見てみてください。</p>
<h2 id="ブース">ブース</h2><img src="/images/2024/20240805a/PXL_20240802_043038785.jpg" alt="" width="1200" height="591" loading="lazy">

<p>Day1の参加報告で紹介し忘れてましたが、Google Cloud Professional資格を持っている人のみが入れる認定資格者ラウンジがあります。このラウンジではコンセント付きのテーブルが置かれており、ちょっとした作業をできます。また今年は資格全冠者向けに限定グッズプレゼント企画があったので、滑り込みで全冠しておいてよかったです。</p>
<p>Day2もDay1と同じブースが出展されているので、Day1で回りきれなかったブースにも足を運ぶことが可能です。所感としてはSaaSを提供している企業ブースに外資系の会社が多く見られました。割と直近で日本ブランチが作られている会社もあり、まだまだ市場として日本は注目されているんだなーと感じました。</p>
<p>この日に回った会社はABC順で以下になります（もちろん、これらの会社以外も出展があります）</p>
<ul>
<li>box</li>
<li>Confluent</li>
<li>Fivetran</li>
<li>Kyndryl</li>
<li>LumApps</li>
<li>MongoDB</li>
<li>Okta</li>
<li>SUSE</li>
<li>ThoughtSpot</li>
</ul>
<h2 id="まとめ">まとめ</h2><p>Day1、Day2ひっくるめた所感としては、Google CloudやGoogle WorkspaceとGeminiの融合を加速させていくぜ！ という気持ちが感じられました。Geminiの利用を標準化させていくことによって競合クラウドベンダーとの差分化を狙っていけるのではないでしょうか。ただ、Office365やOpenAIを擁するAzureに対してどのように戦っていくかは気になるところです。</p>
<p>元々マネージドサービスの利用が増えつつある潮流はありましたが、Geminiの活用によってノンマネージドで煩雑なインフラ構築も益々楽になっていくでしょう。今に始まった話ではないですが、Google Cloudやインフラ・DevOpsの知識でご飯を食べている自分としては身の振り方を考えていかないとなーと今回の参加で痛感させられました。<br>その反面、生成AIのおかげでフルスタックな開発が一人でも回せるようになっており、やったもん勝ち・手を動かしたもん勝ちな世界になってきています。自分も色々手を出してみようとやる気を貰える参加にもなりました。</p>
<p>イベント参加は色々考えさせられるきっかけを貰えるので、もし時間があればぜひオフラインでこういったイベントに参加してみることをおススメします！</p>
]]></content>
    <summary type="html">8/1-8/2にパシフィコ横浜で開催されているGoogle Cloud Next Tokyo '24に同じプロジェクトのメンバー数名で参加してきました。Day2（8/2）の参加レポートです。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="GoogleCloud" scheme="https://future-architect.github.io/tags/GoogleCloud/"/>
    <category term="GoogleCloudNext" scheme="https://future-architect.github.io/tags/GoogleCloudNext/"/>
    <category term="GoogleCloudNext2024" scheme="https://future-architect.github.io/tags/GoogleCloudNext2024/"/>
    <category term="Spanner" scheme="https://future-architect.github.io/tags/Spanner/"/>
    <category term="参加レポート" scheme="https://future-architect.github.io/tags/%E5%8F%82%E5%8A%A0%E3%83%AC%E3%83%9D%E3%83%BC%E3%83%88/"/>
  </entry>
  <entry>
    <title>Google Cloud Next Tokyo '24 1日目参加レポート</title>
    <link href="https://future-architect.github.io/articles/20240802a/"/>
    <id>https://future-architect.github.io/articles/20240802a/</id>
    <published>2024-08-01T15:00:00.000Z</published>
    <updated>2024-08-01T15:00:00.000Z</updated>
    <author><name>岸下優介</name></author>
    <content type="html"><![CDATA[<img fetchpriority="high" src="/images/2024/20240802a/PXL_20240801_042608193.jpg" alt="" width="1200" height="683">

<h2 id="はじめに">はじめに</h2><p>8&#x2F;1-8&#x2F;2にパシフィコ横浜で開催されているGoogle Cloud Next Tokyo ‘24に同じプロジェクトのメンバー数名で参加してきました。本記事はDay1（8&#x2F;1）の参加レポートになります。</p>
<h2 id="基調講演">基調講演</h2><p>基調講演ではオープニングトークに始まり、Google Cloudが現在注力している事業、新サービスの公開、そしてGoogle Cloudを利用する数々の会社の事例紹介があります。</p>
<p>昨年に引き続き今年も生成AI関連の話が中心でしたが、昨年との大きな違いとしては生成AIのモデル単体の話よりも、 画像・音声・文章を組み合わせた<strong>マルチモーダルエージェントを活用していこうぜ！</strong> というビジネスへ活用していく意気込みが感じられるような講演でした。たった1年で画像や音声も扱えるようになり、更に発話もするようになっており、生成AIの進化は目まぐるしいです。</p>
<p>また、Googleは生成AI開発に対して一気通貫で対応しており…</p>
<ul>
<li>一時期話題となった千葉県印西市のデータセンター開設話から海底ケーブルの増設によるインフラ強化</li>
<li>Vertex AIを通じたGoogleのモデルだけに閉じないモデルの提供</li>
<li>Googleの検索エンジンを生成AIのグラウンディングに活用可能</li>
<li>ノーコード・ローコード・フルコードで開発できる開発環境の提供</li>
<li>Gemini for Google Workspaceによるマルチモーダルエージェントのビジネス導入</li>
<li>Gemsを通じたカスタマイズAIエージェントの構築</li>
</ul>
<p>…といったフルラインナップの紹介がありました。特にGoogleの大きな強みである検索エンジンを生成AIのグラウンディングに使えるのはGoogleならではでないでしょうか。</p>
<p>また本日、Geminiモデル in Japanを紹介しており、Geminiが学習したり・生成したデータを日本国内のデータセンターのみに留めることできるようになるとの発表がありました。データにセンシティブな企業としては非常に嬉しい発表ではないでしょうか。</p>
<p>個人的にはGoogleはWorkspaceの数々のサービスとGeminiが連携できるところがとても強いなーと感じました。今日の講演中にあったデモですが…</p>
<ul>
<li>GeminiからGmailを呼び出して(<code>@Gmail</code>と打つと呼び出せるらしい)数々のメールから依頼されているタスクの優先順位を決めてもらう</li>
<li>Driveにある資料を読み込ませて(<code>@Drive</code>と打つ)比較資料を作成</li>
<li>作成してもらった資料を組み合わせてDocsでレポートを生成</li>
<li>更にSlidesで発表資料も生成</li>
</ul>
<p>…なんてことができてしまい、いかに生成AIを上手く仕事で使うかという時代が既に来ちゃってるんだなーと思いました。</p>
<h2 id="セッション講演">セッション講演</h2><p>セッション講演はGoogle Cloud主催のサービス・ベストプラクティスの紹介や事業会社・パートナー企業におけるGoogle Cloudの活用事例などがあります。講演後はAsk the speakerという形で発表者に直接質問をしに行くことができるので、発表資料には載っていなかったつらみなどを聞くことも可能です。</p>
<p>活用事例の講演では最近のトレンドを知ることができたり、アーキ図からサービスの組み合わせ方法を知れたりと新たな発見が多く、学びになります。また、業種毎でデータの集め方が違ったり、ペインポイントが異なる場合が多かったりするので、視野を広げる意味でもセッション講演は非常に楽しめます。</p>
<p>個人的にはデロイト トーマツ コンサルティング合同会社、三菱自動車工業株式会社、Google Cloudによる車両データを活用した各種パートナーとのサービス連携 × モビリティ ビジネス推進の発表に出てきたデータプラットフォーム話が良かったです。特に、データの収集の仕方は業種によっては違えど、データをデータレイクに集めて、整形してデータウェアハウスに落とし込み、後は用途に合わせてデータマートを作ってBIで可視化するという部分は基本なんだなーという学びを得られました。</p>
<h2 id="ブース">ブース</h2><img src="/images/2024/20240802a/image.png" alt="" width="995" height="835" loading="lazy">

<p>ブース展示にはGoogle側が用意している展示からパートナー企業、SaaS企業の展示があります。写真で載せているブースでは目の前のレールコースターをミニカーが走り、IR LEDセンサーを通じてRaspberry Piが走行データを取得、Google CloudのNoSQLサービスであるBigtableへ連携され、BigQueryやVertexAI Workbenchで解析するというデモでした。ちなみにこのデモは今年4月にラスベガスで開かれたGoogle Cloud Next ‘24で展示していたものをそのまま持ってきたそうです。</p>
<p>こういうデモが触れるのは現地参加ならではですね。他にも手動でトラフィックをさばいてGoogleのLoadbalancerと勝負するデモなんかもありました。</p>
<p>またパートナー企業やSaaS企業の展示を聞くことで最近の動向や知識のアップデートができるのでおススメです。特にSaaS界隈は全く知識が追い付いていないことを今回実感させられました。</p>
<p>ロゴは知ってるけれど何の会社か知らなかったSnyk、CDNの会社でホットな会社だと何かのブログで見たけど詳しくは知らないFastly、NoSQLということだけは知っているMongoDBの話を聞くことができてよかったです。Snykの話を聞いたあとに、「<strong>S</strong>o <strong>n</strong>ow <strong>y</strong>ou <strong>k</strong>nowでSnykだ」と言われたことが個人的にはツボでした。</p>
<h2 id="まとめ">まとめ</h2><p>本記事ではGoogle Cloud Next Tokyo ‘24の参加レポートを執筆させて頂きました。出不精な自分ですが、こういうイベントへ参加する度に、やはり人に会って話をするのはとても大切だなーと毎回実感させられます。ぜひ自分が気になるイベントがあれば参加してみることをおススメします！</p>
<p>特にこういった大規模イベントで貰えるSwagが醍醐味でもあります！</p>
<img src="/images/2024/20240802a/PXL_20240801_151358344.jpg" alt="" width="1200" height="675" loading="lazy">

<p>（2024.8.5追記）Google Cloud Next Tokyo ‘24 2日目参加レポート 公開しました！</p>
]]></content>
    <summary type="html">8/1-8/2にパシフィコ横浜で開催されているGoogle Cloud Next Tokyo '24に同じプロジェクトのメンバー数名で参加してきました。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="Gemini" scheme="https://future-architect.github.io/tags/Gemini/"/>
    <category term="GoogleCloud" scheme="https://future-architect.github.io/tags/GoogleCloud/"/>
    <category term="GoogleCloudNext" scheme="https://future-architect.github.io/tags/GoogleCloudNext/"/>
    <category term="GoogleCloudNext2024" scheme="https://future-architect.github.io/tags/GoogleCloudNext2024/"/>
    <category term="参加レポート" scheme="https://future-architect.github.io/tags/%E5%8F%82%E5%8A%A0%E3%83%AC%E3%83%9D%E3%83%BC%E3%83%88/"/>
  </entry>
  <entry>
    <title>【合格記】Professional Google Workspace Administrator認定資格を振り返る</title>
    <link href="https://future-architect.github.io/articles/20240801a/"/>
    <id>https://future-architect.github.io/articles/20240801a/</id>
    <published>2024-07-31T15:00:00.000Z</published>
    <updated>2024-07-31T15:00:00.000Z</updated>
    <author><name>岸下優介</name></author>
    <content type="html"><![CDATA[<img fetchpriority="high" src="/images/2024/20240801a/images.png" alt="" width="224" height="224">

<h2 id="はじめに">はじめに</h2><p>Google Cloud認定資格全冠を目指すべく、Professional Cloud DevOps Engineer 認定資格（PCDE）を受けてきました。無事に合格できたので、本記事ではざっくりとした所感を書いていきたいと思います。</p>
<p>また本試験はGoogle Cloudパートナー企業向けのバウチャーを活用して受験しました。大変感謝しております！</p>
<p>Google Cloud 認定資格関連の過去記事：</p>
<ul>
<li>【合格記】Google Cloud Professional Cloud DevOps Engineer認定資格を振り返る</li>
<li>【合格記】Professional Cloud Database Engineer認定資格を振り返る</li>
<li>【合格記】Google Cloud Professional Developer認定資格を振り返る</li>
<li>【合格体験記】Google Cloudの入門試験：Cloud Digital Leader</li>
<li>【合格記】Google Cloud Professional Cloud Security Engineer認定資格を振り返る</li>
<li>【合格記】Google Cloud Professional Data Engineer認定資格を振り返る</li>
<li>【合格記】Google Cloud Professional Machine Learning Engineer認定資格を振り返る</li>
<li>Google Cloud Professional Cloud Architectの再認定に合格しました</li>
<li>GCP Professional Cloud Network Engineer に合格しました</li>
<li>GCP Associate Cloud Engineer 合格記</li>
</ul>
<p>これでFuture Tech BlogもGoogle Cloud認定資格全冠達成です！</p>
<h2 id="試験と出題範囲">試験と出題範囲</h2><p>公式の出題範囲と、実際に自分が受けた際の所感は以下になります。</p>
<h3 id="オブジェクトの管理">オブジェクトの管理</h3><ul>
<li>組織の統合<ul>
<li>Domain Shared Contacts APIを利用した外部連絡先の取得・更新</li>
<li>Google Cloud Directory Syncを利用した組織のLDAPと同期させたライセンスの更新</li>
<li>組織単位（OU）を利用した複数組織の共存</li>
</ul>
</li>
<li>ポリシーの設定<ul>
<li>コンプライアンスルールに基づくメールコンテンツのフィルタリング</li>
</ul>
</li>
<li>データ保護<ul>
<li>組織の外部共有を管理し、不意な情報漏洩を防ぐ</li>
<li>信頼済みドメインを設定することで、ホワイトリスト式の共有許可を設定する</li>
</ul>
</li>
</ul>
<h3 id="サービスの構成">サービスの構成</h3><ul>
<li>セキュリティの向上<ul>
<li>Gmailにおけるセキュリティサンドボックスを利用した有害な添付ファイルの検出</li>
<li>スパムメールの隔離</li>
</ul>
</li>
<li>サービス利用の制限<ul>
<li>会社所有のデバイスを事前に登録しておき、そのデバイスのみでの使用を許可</li>
</ul>
</li>
<li>共有ドライブにおけるロールの理解<ul>
<li>コントリビューター</li>
<li>コンテンツマネージャー</li>
<li>編集者</li>
</ul>
</li>
<li>データ地域の設定<ul>
<li>データの保存する地域を設定することで、各地域の法律を遵守する</li>
</ul>
</li>
</ul>
<h3 id="トラブルシューティング">トラブルシューティング</h3><ul>
<li>誤操作時の対応<ul>
<li>誤って削除したアカウントの復元</li>
</ul>
</li>
<li>想定しない挙動への対応<ul>
<li>メールの受信許可設定や隔離設定の確認</li>
</ul>
</li>
<li>パスワードの同期<ul>
<li>Active DirectoryとGoogle Workspace間での同期がなされていることを確認</li>
</ul>
</li>
</ul>
<h3 id="データのアクセスと認証">データのアクセスと認証</h3><ul>
<li>データの共有・コピー<ul>
<li>ビジター共有機能を利用した外部アカウントへのファイル共有</li>
<li>個人用アプリへのデータコピーを制限</li>
</ul>
</li>
<li>Single Sign On（SSO）の導入<ul>
<li>一度のログインで複数の関連するシステムへアクセス可能とする</li>
</ul>
</li>
<li>アカウントの保護<ul>
<li>2段階認証の設定</li>
<li>Context-Aware Accessを設定し、意図しない地域やデバイスからの不正ログインを防ぐ</li>
<li>セキュリティ監査ログを利用した通常と異なるサインインパターンを検出する</li>
</ul>
</li>
</ul>
<h3 id="ビジネス-イニシアチブのサポート">ビジネス イニシアチブのサポート</h3><ul>
<li>Google Vaultの利用<ul>
<li>監査や法的調査に向けた案件の作成とデータのエクスポート</li>
<li>セキュリティ調査対象の社員にバレないように情報を保護し、調査する</li>
</ul>
</li>
<li>Googleグループの利用<ul>
<li>一部のユーザーのみに対するポリシーの例外設定</li>
<li>メール通知の共同受信箱やグループとして返信する機能の設定</li>
</ul>
</li>
<li>カスタムロールの活用<ul>
<li>既存の権限では操作できる範囲が広すぎる・狭すぎる場合に許可範囲を絞ったロールを作成可能</li>
</ul>
</li>
<li>各Editionの理解<ul>
<li>4つのGoogle Workspace Editionが存在<ul>
<li>Business</li>
<li>Education</li>
<li>Enterprise</li>
<li>Essentials</li>
</ul>
</li>
<li>組織の大きさによって使い分ける必要がある</li>
</ul>
</li>
</ul>
<h3 id="全体的な所感">全体的な所感</h3><p>Google Cloudを利用するエンジニアにとって、Google Workspaceの一員としてGmailやGoogle Calender、Google Driveなどは頻繁に利用されているかもしれませんが、Workspace自身で設定されている内容自体は馴染みの薄いものだと思います。</p>
<p>実際に自分も類似のサービスであるCloud Identityを触ったことがあったため若干の知見はありましたが、70％くらいは初見でした。</p>
<p>ただ、ファイルの共有方法やGmailの設定などGoogle Workspaceを利用したことがある方であれば、一度は見たことがある内容も多いので、そこらへんの記憶を頼りに解いていけるのではないでしょうか。</p>
<p>もし手を動かして勉強したい場合は、Google Cloud内でCloud Identityを利用することでざっくりと触ってみることができます<sup id="fnref:1">1</sup>。</p>
<h2 id="勉強方法">勉強方法</h2><p>どの試験もそうですが、4～5択から正解を選ぶ選択式試験なので模擬試験などで場数をこなすことが大事だと思います。</p>
<ul>
<li>Google Cloud公式提供の模擬試験を受験する</li>
<li>Udemyなどのオンライン学習サービスで模擬試験を購入し勉強する<ul>
<li>https://www.udemy.com/course/2024google-cloud-professional-workspace-administrator</li>
</ul>
</li>
</ul>
<p>正解の選択肢を暗記するというよりは、間違った問題に対してドキュメントを読みことが大切です。なぜその選択肢が正解なのかを理解することで他の問題にも応用できるようになっていきます。</p>
<h2 id="まとめ">まとめ</h2><p>本記事ではPGWAを受けた際の所感を記載させて頂きました。正直のところ、資格全冠を目指さなかったら受けていなかった試験だと思うので、Google Workspaceについて勉強になりました。特にGoogle VaultやSecurity Sandboxというサービスは存在すら知っておらず、今回の試験で学びになりました。また、Google Workspace向けのドキュメントはGoogle Cloudと比べてめちゃくちゃあっさりとした内容で面食らいました😂</p>
<p>これにてGoogle Cloud認定資格全冠達成です。やったー！</p>
<div id="footnotes"><hr><div id="footnotelist"><ol style="list-style:none; padding-left: 0;"><li id="fn:1"><span style="vertical-align: top; padding-right: 10px;">1.</span><span style="vertical-align: top;">但し、ドメインを購入して自身のGoogle Cloudに組織を追加する必要があるため完全無料ではありません。</span> ↩</li></ol></div></div>]]></content>
    <summary type="html">Google Cloud認定資格全冠を目指すべく、Professional Cloud DevOps Engineer 認定資格（PCDE）を受けてきました。無事に合格することができたので、本記事ではざっくりとした所感を書いていきたいと思います</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="GoogleCloud" scheme="https://future-architect.github.io/tags/GoogleCloud/"/>
    <category term="PGWA" scheme="https://future-architect.github.io/tags/PGWA/"/>
    <category term="全冠" scheme="https://future-architect.github.io/tags/%E5%85%A8%E5%86%A0/"/>
    <category term="合格記" scheme="https://future-architect.github.io/tags/%E5%90%88%E6%A0%BC%E8%A8%98/"/>
  </entry>
  <entry>
    <title>【合格記】Google Cloud Professional Cloud DevOps Engineer認定資格を振り返る</title>
    <link href="https://future-architect.github.io/articles/20240731a/"/>
    <id>https://future-architect.github.io/articles/20240731a/</id>
    <published>2024-07-30T15:00:00.000Z</published>
    <updated>2024-07-30T15:00:00.000Z</updated>
    <author><name>岸下優介</name></author>
    <content type="html"><![CDATA[<img fetchpriority="high" src="/images/2024/20240731a/image.png" alt="" width="537" height="560">

<h2 id="はじめに">はじめに</h2><p>Google Cloud認定資格全冠を目指すべく、Professional Cloud DevOps Engineer 認定資格（PCDE）を受けてきました。無事に合格できたので、本記事ではざっくりとした所感を書いていきたいと思います。</p>
<p>また本試験はGoogle Cloudパートナー企業向けのバウチャーを活用して受験しました。大変感謝しております！</p>
<p>Google Cloud 認定資格関連の過去記事：</p>
<ul>
<li>【合格記】Professional Cloud Database Engineer認定資格を振り返る</li>
<li>【合格記】Google Cloud Professional Developer認定資格を振り返る</li>
<li>【合格体験記】Google Cloudの入門試験：Cloud Digital Leader</li>
<li>【合格記】Google Cloud Professional Cloud Security Engineer認定資格を振り返る</li>
<li>【合格記】Google Cloud Professional Data Engineer認定資格を振り返る</li>
<li>【合格記】Google Cloud Professional Machine Learning Engineer認定資格を振り返る</li>
<li>Google Cloud Professional Cloud Architectの再認定に合格しました</li>
<li>GCP Professional Cloud Network Engineer に合格しました</li>
<li>GCP Associate Cloud Engineer 合格記</li>
</ul>
<h2 id="試験と出題範囲">試験と出題範囲</h2><p>公式の出題範囲と、実際に自分が受けた際の所感は以下になります。</p>
<h3 id="DevOps-向けに-Google-Cloud-組織をブートストラップする">DevOps 向けに Google Cloud 組織をブートストラップする</h3><ul>
<li>再現性のあるインフラストラクチャ構築<ul>
<li>Deployment ManagerやTerraformなどのIaCツールを活用</li>
</ul>
</li>
<li>組織内で統一されたポリシーの適用<ul>
<li>リソース階層とIAMの適用範囲への理解<ul>
<li>フォルダを活用したプロジェクトの分離</li>
</ul>
</li>
<li>組織ポリシーの活用<ul>
<li>サービスアカウントのKey Fileを作成させたくない</li>
<li>外部ドメインへのIAM付与を禁止したい</li>
<li>など</li>
</ul>
</li>
</ul>
</li>
<li>ログの管理<ul>
<li>ログシンクを活用した複数のPJを跨いだログ集約</li>
<li>ログの長期保管に向けたCloud StorageにおけるStorage Classの選択</li>
</ul>
</li>
</ul>
<h3 id="サイト信頼性エンジニアリングのプラクティスをサービスに適用する">サイト信頼性エンジニアリングのプラクティスをサービスに適用する</h3><ul>
<li>ポストモーテムの導入<ul>
<li>失敗を繰り返さないインシデントレポート</li>
<li>人を批判せずにシステムを批判する</li>
<li>しくじりを共有しやすい文化を醸成する</li>
</ul>
</li>
<li>Service Level Agreement(SLA)&#x2F;Service Level Objective(SLO)&#x2F;Service Level Indicator(SLI)の導入<ul>
<li>カスタマー目線に立ったシステムモニタリングを導入する</li>
<li>Golden Signalsの導入</li>
<li>Cloud Monitoringを利用したSLOの設定</li>
<li>エラーバジェットに基づいたリリース計画</li>
</ul>
</li>
<li>インシデント発生時の対応方法<ul>
<li>ステークホルダーへの情報共有</li>
<li>インシデントに対応するための各種ロール設定<ul>
<li>Incident Commander</li>
<li>Operation Lead</li>
<li>Communication Lead</li>
<li>など</li>
</ul>
</li>
<li>バージョンのロールバックを通じた原因の切り分け</li>
</ul>
</li>
</ul>
<h3 id="サービス-パフォーマンスを最適化する">サービス パフォーマンスを最適化する</h3><ul>
<li>パフォーマンスに影響を及ぼしている原因の探索<ul>
<li>Cloud Profilerを活用したアプリケーションのCPU・メモリ使用量などの可視化</li>
<li>Cloud Traceを活用したリクエスト時間、レイテンシといった通信関連の問題解決</li>
</ul>
</li>
<li>Googleのサービスを活用<ul>
<li>Recommender APIを利用した推奨事項の適用</li>
</ul>
</li>
<li>サービスのキャパシティ計画とFinOps<ul>
<li>プロジェクトや組織のクオータへの理解とCloud Quotasの活用</li>
<li>確約利用割引を利用した費用の最適化</li>
</ul>
</li>
</ul>
<h3 id="サービスの-CI-CD-パイプラインを構築および実装する">サービスの CI &#x2F; CD パイプラインを構築および実装する</h3><ul>
<li>サービスのデリバリを自動化する<ul>
<li>Cloud Buildを活用したパイプラインの実装</li>
<li>テスト方法への理解<ul>
<li>ユニットテスト</li>
<li>統合テスト</li>
<li>受入テスト</li>
<li>スモークテスト</li>
<li>シャドーテスト</li>
<li>など</li>
</ul>
</li>
<li>Binary Authorizationを利用したイメージの信頼性担保</li>
<li>Artifact Registryにおける脆弱性スキャン</li>
<li>Cloud KMSを利用した暗号化</li>
</ul>
</li>
<li>APIのバージョニング<ul>
<li>サードパーティの開発者を混乱させないバージョニング戦略を策定<ul>
<li>廃止する前に通知する</li>
<li>移行期間を設ける</li>
<li>下位互換性を用意しておく</li>
<li>など</li>
</ul>
</li>
</ul>
</li>
<li>サービスのリリース<ul>
<li>シチュエーションに応じた適切なリリース方法の選択<ul>
<li>カナリア</li>
<li>ブルーグリーン</li>
</ul>
</li>
<li>Cloud Runにおけるロールバック、カナリーリリース、トラフィック移行</li>
</ul>
</li>
</ul>
<h3 id="サービスのモニタリング戦略を実装する">サービスのモニタリング戦略を実装する</h3><ul>
<li>モニタリングへの理解<ul>
<li>Cloud Monitoringのカスタムダッシュボード構築</li>
<li>Compute EngineへOps Agentを導入しメトリクスを収集</li>
<li>問題に対して見るべきメトリクスの選択</li>
<li>Monitoring Query Languageを利用したログの探索やアラート設定</li>
<li>ネットワークモニタリングにはVPC Flow Logsの活用</li>
</ul>
</li>
</ul>
<h3 id="全体的な所感">全体的な所感</h3><p>DevOpsということもあり、試験範囲となるGoogle Cloudのサービスはかなり多岐に及びます。その中でも特にGoogle Kubernetes Engine（GKE）・Cloud Runに関連した問題が多く、これらのサービスへの理解はマストとなりました。また、Googleが提唱するSite Reliability Engineering（SRE）も試験範囲に含まれており、そのベストプラクティスに関する知識が問われるため、過去にSRE本を読んでおいてよかったなと思いました。SREの内容に関してはGoogleが無料で提供しているWebサイトもあるので、こちらでも良さそうです。</p>
<p>全冠を目指す際の順番的にはProfessional Developer、Professional Cloud Security Engineerを取ってから本試験を受験すると、試験範囲的に被っている部分も多く勉強しやすいのかなと思いました。</p>
<h2 id="勉強方法">勉強方法</h2><p>どの試験もそうですが、4～5択から正解を選ぶ選択式試験なので模擬試験などで場数をこなすことが大事だと思います。</p>
<ul>
<li>Google Cloud公式提供の模擬試験を受験する</li>
<li>Udemyなどのオンライン学習サービスで模擬試験を購入し勉強する<ul>
<li>https://www.udemy.com/course/2023google-cloud-professional-devops-engineer</li>
</ul>
</li>
</ul>
<p>正解の選択肢を暗記するというよりは、間違った問題に対してドキュメントを読みことが大切です。なぜその選択肢が正解なのかを理解することで他の問題にも応用できるようになっていきます。</p>
<h2 id="まとめ">まとめ</h2><p>本記事ではPCDEを受けた際の所感を記載させて頂きました。Google CloudのProfessional認定資格では、合格特典が貰えるのでモチベが上がります。ただ、アパレル系特典は長袖しかないので今後は半袖が追加されることを期待しております🤞</p>
<img src="/images/2024/20240731a/image_2.png" alt="" width="1200" height="598" loading="lazy">
]]></content>
    <summary type="html">Google Cloud認定資格全冠を目指すべく、Professional Cloud DevOps Engineer 認定資格（PCDE）を受けてきました。無事に合格することができたので、本記事ではざっくりとした所感を書いていきたいと思います。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="GoogleCloud" scheme="https://future-architect.github.io/tags/GoogleCloud/"/>
    <category term="PCDE" scheme="https://future-architect.github.io/tags/PCDE/"/>
    <category term="合格記" scheme="https://future-architect.github.io/tags/%E5%90%88%E6%A0%BC%E8%A8%98/"/>
  </entry>
  <entry>
    <title>クラウドロックインされないアーキテクチャ「Cloud Agnostic Architecture」のすすめ</title>
    <link href="https://future-architect.github.io/articles/20240617b/"/>
    <id>https://future-architect.github.io/articles/20240617b/</id>
    <published>2024-06-16T15:00:01.000Z</published>
    <updated>2024-06-16T15:00:01.000Z</updated>
    <author><name>武田大輝</name></author>
    <content type="html"><![CDATA[<p>この記事はQiitaのアドベントカレンダー記事のリバイバル公開です。<br>※ 当時の記事から、一部表現を見直し加筆しています。</p>
<h2 id="はじめに">はじめに</h2><p>先日ガートナーのレポートで「多くの企業において、特定のクラウドベンダーにシステムを集中させるリスクの重要度が上昇している」との発表がありました。</p>
<p>https://www.gartner.com/en/newsroom/press-releases/2023-10-30-gartner-says-cloud-concentration-now-a-significant-emerging-risk-for-many-organizations</p>
<p>日本においてクラウドの活用はますます進んでいる一方で、特定の Cloud Service Provider（CSP）にロックインされるリスクについては、常に議論の余地があると考えています。<br>本記事では、特定のクラウドに強く依存しないアーキテクチャについて「Cloud Agnostic Architecture」という言葉を用いて整理していきます。</p>
<h2 id="Cloud-Agnostic-Architecture-とは">Cloud Agnostic Architecture とは</h2><p>Cloud Agnostic<sup id="fnref:1">1</sup> Architectureとは「特定のクラウドに依存しないアーキテクチャ」を意味します。これはクラウドプラットフォーム自体を利用しないという意味ではなく、複数のクラウドプラットフォーム間（ないしはオンプレミスとクラウドのハイブリッドモデル間）で、アプリケーション、ツール、サービスを含むワークロードをシームレスに移植できるように設計することを意味しています。</p>
<p>このアーキテクチャには次のようなメリットがあります。</p>
<ul>
<li><p><strong>クラウドロックイン<sup id="fnref:2">2</sup>の回避</strong><br>何かしらの事情により今利用しているクラウドプラットフォームから他のクラウドプラットフォームへ移行しなければならない（もしくは移行することでコスト面などの恩恵を受けられる）状況が発生した場合に、コストや時間をかけずに移行することが可能となります。</p>
</li>
<li><p><strong>より広範なロケーションへのシステム展開</strong><br>複数のクラウドプラットフォームを利用することでより多くのロケーション（リージョン）にシステムを展開できるだけではなく、各ロケーションに適したクラウドプラットフォームを選択できるようになります。<br>これは例えば、グローバルにシステムを展開するようなケースおいて、通常は AWS を利用するが、中国におけるシステム展開においては、中国の CSP（Alibaba CloudやTencent Cloud）を利用することで、法制度的なリスクを最小化するといったことが考えられます。</p>
</li>
<li><p><strong>マルチクラウド構成の容易な実現</strong><br>DR 対策として複数のクラウドプラットフォーム上にシステムを展開しておくなど、冗長デプロイが必要なマルチクラウド構成をとることが容易になります。</p>
</li>
</ul>
<h2 id="Cloud-Agnostic-Architecture-を実現するためのアプローチ">Cloud Agnostic Architecture を実現するためのアプローチ</h2><p>この章では Cloud Agnostic Architecture を実現するためのいくつかのアプローチを紹介します。</p>
<h3 id="OSS技術の採用">OSS技術の採用</h3><p>CSPプロプライエタリなマネージドサービスを利用するのではなく、マネージドなオープンソースサービス（ないしはOSS互換性のあるサービス）を利用や、真に必要な場合はOSSのセルフホスティングを行います。</p>
<p>AWS を例に OSS &#x2F; OSS互換のサービスとプロプライエタリなサービスの一例をみてみると、選択肢がいくつかあることがわかるでしょう。</p>
<img fetchpriority="high" src="/images/2024/20240617b/image.png" alt="image.png" width="760" height="610">

<p>主要な OSS &#x2F; OSS互換のサービスは、基本的にそれ自体が業界標準的な技術仕様に準拠する形で設計されており、メジャーなものは多くのクラウドプラットフォームにてマネージドサービスとして提供されているため（もしくは提供されていない場合でも、IaaSとしてのコンピューティングサービス上にホスティングすることで、クラウドプラットフォームに依存せず利用できるため）、積極的に利用することでクラウドの移植性を高めることができます。</p>
<h3 id="コンテナ技術の採用">コンテナ技術の採用</h3><p>Dockerに代表されるコンテナ型の仮想化技術によりホスト環境とアプリケーション環境を分離することで、アプリケーションのポータビリティが向上し、別のクラウドプラットフォームにアプリケーションを移行しやすくなります。</p>
<h3 id="独立性のある-DevOps-の実践">独立性のある DevOps の実践</h3><p>特定のクラウドに依存しない DepOps のツールやサービスを活用し、ワークフローを自動化することで、別のクラウドプラットフォームへのスイッチングコストを低くできます。具体的にどのようなものなのか、いくつか例を紹介しましょう。</p>
<h4 id="Infrastructure-as-Code">Infrastructure as Code</h4><p>CSP プロプライエタリなサービス（例. AWSであればAmazon CloudFormation<br>やAWS CDK, GCPであればCloud Deployment Manager）ではなく、 Terraform や Crossplane に代表される複数のクラウドに対応したOSSのツールを活用することで、特定のクラウドに依存しない IaC を実現できます。</p>
<h4 id="Observability">Observability</h4><p>可観測性（Observability）を実現するためのツールやサービスは数多くありますが、複数のクラウドに対応したものを採用し、一元的なモニタリングを行うことで、特定のクラウドに依存しない独立性の高い Observability 基盤を実現できます。</p>
<p>CNCFのCloud Native Landscapeを見てみても様々なツールやサービスがありますが、OSSを活用する一例としては、データ可視化にGrafana、メトリクス監視にPrometeus、ログ監視にGrafana Loki、トレース監視にGrafana Tempoを採用する（あるいはこれらをマネージドサービスとして提供するGrafana Cloudを利用する）といった形が考えられます。</p>
<p>あるいは New Relic や DataDog といったSaaSを利用することも有効です。もちろんこれらのサービスはマルチクラウドに対応しています。</p>
<p>1点補足をしておくと、CSPプロプライエタリなモニタリングサービスでしか直接メトリクスを取得できないものがある（例. Amazon Aurora や AWS Lambda のメトリクスは Amazon CloudWatchでしか取得できない）ため、CSPプロプライエタリなモニタリングツール（例. AWS であればAmazon CloudWatch）を完全に利用しないというケースはあまり考えられません。Amazon CloudWatch が提供するデータを Prometheus に連携するといったように、独立したObservability 基盤に一元化していくアプローチになります。</p>
<h4 id="CI-CD">CI&#x2F;CD</h4><p>CI&#x2F;CDについても他と同様、CSPプロプライエタリなサービスではなく、特定のクラウドに依存しないツールやサービスを活用してパイプラインを構築することで、クラウドプラットフォームの移植性が高くなります。<br>この領域においては、既に GitHub Actions や Circle CI といった特定のクラウドに依存しないツールやサービスが広く使われており、AWSのCode Family<sup id="fnref:3">3</sup>のようなCSPプロプライエタリなサービスが活用されるケースよりも主流になっています。</p>
<h3 id="適切な抽象化">適切な抽象化</h3><p>アプリケーションのレイヤにおいて、適切に抽象化されたインターフェースを用いてCSPの提供するサービスとやりとりを行うことで、コアとなるビジネスロジックが特定のCSPに依存しない疎結合なつくりが実現できます。これにより、別のクラウドプラットフォームのサービスに切り替えを行う（例. Amazon S3ではなくGCSを使用する）場合でも、既存のソースコードへの影響を最小限に抑えることが可能となります。<br>クリーンアーキテクチャやリポジトリパターンなどを実践して自身でインターフェースを定義するのも良いですし、GoCDK や Apache jclouds のような各クラウドサービスやOSSプロダクトへの透過的なインターフェースを提供するライブラリを活用する方法もあります。</p>
<h2 id="トレードオフを理解する">トレードオフを理解する</h2><p>Cloud Agnostic Architecture はそれ自体が銀の弾丸ではないため、トレードオフを理解した上で採用することが重要となります。<br>先述したように Cloud Agnostic Architecture を採用することで、クラウドの移植性が向上します。一方で、クラウド非依存を目指すということは、同時に「クラウドのネイティブ機能を最大限活用しない」という判断を（多かれ少なかれ）していることでもあり、常にクラウドプラットフォーム間の差異を抽象化することを意識する必要があります。そのため、時には複雑性が増し、プロダクトを市場に投入するまでの時間が大きくなる可能性もあります。</p>
<p>CSPプロプライエタリなサービスのメリットの1つとして「サービス間のシームレスな連携」が挙げられますが、ここでは具体的な例として、オブジェクトストレージへの操作をトリガーとして、非同期処理を実行するケースを考えてみましょう。</p>
<p>AWSネイティブなサービス&#x2F;機能を採用する場合、S3 のイベント通知を利用して、Lambda 関数を実行するアーキテクチャが考えられます。<br>S3のイベント通知は At Least Once の到達が保証されてますが、イベントはS3内部でコントロールされるため、オブジェクト操作側の処理でイベントの作成を意識することはありません。また、非同期で呼び出される処理についても、Lambdaの機能として起動トリガーやリトライ回数、DLQの送信先などの設定ができるため、開発者はコアとなる処理のみに集中できます。<br>このようにアプリケーションコードを必要最小限に保ちながら簡単に連携を実現できる点が、このアーキテクチャの1つのメリットだと言えます。</p>
<img src="/images/2024/20240617b/image_2.png" alt="image.png" width="720" height="240" loading="lazy">

<p>一方で、このワークロードを別のクラウドプラットフォームに移植しようとした場合、それは簡単でしょうか。オブジェクトストレージのイベントをトリガーとして処理を実行する機構は移行対象のクラウドプラットフォームに備わっているのでしょうか。備わっていたとして管理対象となっているイベントは充足している<sup id="fnref:4">4</sup>のでしょうか。<br>さらに言えば、非同期で呼び出される処理においては、少なくともイベントをハンドリングする部分の処理はクラウド依存しているため、ソースコードの修正&#x2F;追加が必要となります。<br>このようにクラウドの移植時に困難が生じ得る、そのための変更に時間がかかるというのがこのアーキテクチャのデメリットでもあります。</p>
<p>次にこれを Cloud Agnostic Architecture で実現する例を見てみます。<br>AWSネイティブなS3のイベント機構は利用せず、代わりにマネージド Kafka を使用してイベントメッセージを管理します。またコンピューティンレイヤも コンテナベースのアーキテクチャを採用します。</p>
<img src="/images/2024/20240617b/image_3.png" alt="image.png" width="721" height="280" loading="lazy">

<p>これによりAWSプロプライエタリなサービスに依存する部分が小さくなり、代わりにクラウドの移植性が高まります。<br>ただし、このようなアーキテクチャを採用することで、イベントメッセージの到達保証やエラー時のハンドリングなど、CSPに任せていた部分を自分自身で設計・実装する必要がでてくるかもしれません。また、S3イベント通知と同等の可用性や性能を担保するためには、時には追加のコストが必要になるかもしれません。</p>
<p>このようにそれぞれのアーキテクチャは一長一短であり、トレードオフを理解することが重要です。</p>
<h2 id="クラウド依存する-or-依存しないの2択ではない">クラウド依存する or 依存しないの2択ではない</h2><p>ロックイン自体が「ロックインする or しない」の2値で語られるものではないのと同様、Cloud Agnostic Architecture は 特定のクラウドに「依存する or 依存しない」の2択ではなく「どの程度クラウド間の移植性を高めるか」の度合いで、評価されるべきものです。</p>
<p>例えば、コスト面の観点からAWS Lambda を採用するが、イベントをハンドリングする部分はコアロジックと分離し疎結合な作りにする、イベントソースは原則 API Gateway に限定する、などの方針を持つことで、無尽蔵に依存度が高まらないようにするなどといったように、トレードオフの世界で最適な解を見つけることになります。<br>主要なコンピューティングやデータベースの領域は強く移植性を意識し、運用管理系の機能は最大限クラウドネイティブの恩恵を享受する、という戦略も有効でしょう。</p>
<p>何が最適かというのは、対象となるシステムが置かれている状況に応じてさまざまです。<br>例えば、市場までの投入時間が重要な要件であるスタートアップにおいては、クラウドの移植性を犠牲にしてでも、CSPプロプライエタリなサービスを積極的に利用する方が良いかもしれません。逆に特定のCSPに依存することが大きなリスクとなり得るクリティカルなシステムや、グローバル展開に伴いマルチクラウド対応が前提となるシステムにおいては、クラウドの移植性が重要な要件になることでしょう。</p>
<p>このように唯一の正解はありませんが、1つだけ不正解と言える選択は存在します。<br>それは、ロックインのリスクを適切に評価せず、システム全体としてのポリシーをろくに定めないまま、個別最適を追求してCSPプロプライエタリなサービスを無闇やたらに採用することです。</p>
<p>適切にリスクアセスメントを行った上で、指針を定めることが重要となります。</p>
<h2 id="ロックインは完全に回避できない">ロックインは完全に回避できない</h2><p>最後に Cloud Agnostic Architecture を採用したからといっても、システムにおけるロックインは完全に回避できるものではない点を補足しておきます。<br>システムにおけるロックインは、本記事で取り上げた CSP ロックインだけでなく、プロダクトロックインやバージョンロックイン、スキルロックインなどさまざまな次元に分類<sup id="fnref:5">5</sup>できます。</p>
<p>例えば、CSP ロックインを回避するために、OSS互換のサービスを積極的に採用したとしてもプロダクトロックインを回避できているわけではありません。<br>RDB の世界では ANSI SQL 標準に準拠することで、DBプロダクトの移植性を高めるといった工夫が考えられますが、各ロックインの次元において、ロックインされることによるリスクを適切に評価した上で、どこまで対応するかを判断することが求められます。</p>
<h2 id="参考">参考</h2><ul>
<li>Don’t get locked up into avoiding lock-in</li>
<li>Modern cloud applications: Do they lock you in?</li>
<li>開発におけるロックインのリスク評価と考え方</li>
<li>ベンダーロックインを解きほぐしていくために</li>
</ul>
<div id="footnotes"><hr><div id="footnotelist"><ol style="list-style:none; padding-left: 0;"><li id="fn:1"><span style="vertical-align: top; padding-right: 10px;">1.</span><span style="vertical-align: top;">Agnosticとは直訳すると「不可知論者」ですが “単語 + agnostic” で「～（単語）に依存しない」という意味になります。</span> ↩</li><li id="fn:2"><span style="vertical-align: top; padding-right: 10px;">2.</span><span style="vertical-align: top;">クラウドロックインとは特定のクラウドプラットフォームに過度に依存することで、別のクラウドプラットフォームへの移行が困難になってしまう（=スイッチングコストが高い）状態のことを指します。</span> ↩</li><li id="fn:3"><span style="vertical-align: top; padding-right: 10px;">3.</span><span style="vertical-align: top;">Code Family とは AWS CodeCommit, AWS CodeArtifact, AWS CodeBuild, AWS CodeDeploy, AWS CodePipelineを指します。</span> ↩</li><li id="fn:4"><span style="vertical-align: top; padding-right: 10px;">4.</span><span style="vertical-align: top;">例えば AWS S3 と Google Cloud Storage は両方ともイベントトリガーの機構を持ちますが、イベントタイプには差異があります。</span> ↩</li><li id="fn:5"><span style="vertical-align: top; padding-right: 10px;">5.</span><span style="vertical-align: top;">Don't get locked up into avoiding lock-in ではロックインは合計8つの次元で分類されています。</span> ↩</li></ol></div></div>]]></content>
    <summary type="html">この記事はQiitaのアドベントカレンダー記事のリバイバル公開です。※ 当時の記事から、一部表現を見直し加筆しています。先日ガートナーのレポートで「多くの企業において、特定のクラウドベンダにシステムを集中させるリスクの重要度が上昇している」との発表がありました。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="AWS" scheme="https://future-architect.github.io/tags/AWS/"/>
    <category term="GoogleCloud" scheme="https://future-architect.github.io/tags/GoogleCloud/"/>
    <category term="アーキテクチャ" scheme="https://future-architect.github.io/tags/%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3/"/>
    <category term="ベンダーロックイン" scheme="https://future-architect.github.io/tags/%E3%83%99%E3%83%B3%E3%83%80%E3%83%BC%E3%83%AD%E3%83%83%E3%82%AF%E3%82%A4%E3%83%B3/"/>
  </entry>
  <entry>
    <title>AWS初心者が【日本語版】AWS Cloud Quest: Cloud Practitionerをプレイしてみた</title>
    <link href="https://future-architect.github.io/articles/20240606a/"/>
    <id>https://future-architect.github.io/articles/20240606a/</id>
    <published>2024-06-05T15:00:00.000Z</published>
    <updated>2024-06-05T15:00:00.000Z</updated>
    <author><name>平井隆太</name></author>
    <content type="html"><![CDATA[<h2 id="はじめに">はじめに</h2><p>みなさん初めまして。2023年10月に新卒でフューチャー株式会社に入社したCSIG&#x2F;Vulsチーム所属の平井と申します。</p>
<p><strong>AWS Cloud Questの魅力や使い方、そして実際にプレイしてみた感想をAWS初学者の目線でお伝えします。</strong></p>
<p>EC2・RDSなどAWS主要サービスの機能・役割に対する知識はあるけど、より実用的な知識を学びたい方、ゲーム感覚で楽しく学びたい方は必見です！<br>（上記の知識がないという方はまずこちらを参考に学習を進めることをオススメします！）</p>
<div class="note-container note-info"><span class="note-icon"></span><div><p>本記事ではAWS Cloud Quest: <strong>Cloud Practitioner</strong> に絞って解説します。</p></div></div>

<h2 id="AWS-Cloud-Questとは">AWS Cloud Questとは</h2><p>一言でいうと <strong>実用的なAWS Cloud スキルを身につけることができるロールプレイングゲーム」</strong> です。<br>もともと英語版でのみ展開されていましたが、2023年10月より「クラウドプラクティショナーロール」が日本語でプレイできるようになりました（参考）</p>
<p><strong>しかも無料！（ここ大事）</strong></p>
<p>その他のロールは以下のようになっております。<br><img fetchpriority="high" src="/images/2024/20240606a/cq_jp_2-1024x313.png" alt="" width="1024" height="313"></p>
<h2 id="学習できるサービス内容">学習できるサービス内容</h2><p>AWS Cloud Questでは以下の基礎的なサービスや概念について学ぶことができます。</p>
<ul>
<li>Amazon S3</li>
<li>Amazon EC2</li>
<li>AWS Pricing Calculator</li>
<li>Amazon VPC</li>
<li>Amazon DynamoDB</li>
<li>Amazon RDS</li>
<li>AWS IAM</li>
<li>Amazon Elastic File System</li>
<li>Amazon EC2 Auto Scaling</li>
<li>ELB</li>
</ul>
<p>またゲームの後半では、複数のサービスを組み合わせてソリューションを構築します。</p>
<p>それではさっそくAWS Cloud Questをプレイする準備に入っていきましょう。</p>
<h2 id="事前準備">事前準備</h2><p>事前に準備することは<strong>AWS Skill Builderへの登録</strong>と<strong>日本語の設定</strong> です。</p>
<h3 id="AWS-Skill-Builderへの登録">AWS Skill Builderへの登録</h3><p>まずAWS Cloud Questで検索し、AWS Cloud Questのページへ飛びます。<br>「クラウドプラクティショナーを無料で試す」を押下します。</p>
<img src="/images/2024/20240606a/image_(3).png" alt="" width="1200" height="557" loading="lazy">

<p>AWS training and certificationのAWS Cloud Quest: Cloud Practitionerのページへ飛ぶので、「ENROLL」を押します。</p>
<img src="/images/2024/20240606a/image_(4).png" alt="" width="1200" height="562" loading="lazy">

<p>「ENROLL」を押すとアカウントの作成が求められるので、作成します（すでにAWSアカウントがある人はサインインでOK）</p>
<img src="/images/2024/20240606a/image_(5).png" alt="" width="1140" height="582" loading="lazy">

<p>アカウントの作成はこれで終わりです。</p>
<p>以下の画面で「START LEARNING NOW」を押し、遷移先で「START NOW」を押すとプレイ画面に移ります。</p>
<img src="/images/2024/20240606a/32e49e84-1d04-3796-4082-4b1cb3acd90c.png" alt="" width="1200" height="600" loading="lazy">

<h3 id="日本語の設定">日本語の設定</h3><p>次に言語の設定に進んでいきます。<br>スタート画面に移ったら、右上の歯車マークから設定に移動します。<br><img src="/images/2024/20240606a/77dad39e-61f3-8a26-fb0d-75cf46acd714.png" alt="" width="1200" height="596" loading="lazy"></p>
<p>設定画面に移ったら、「Language」を選択。<br><img src="/images/2024/20240606a/ca1909bb-6f73-a9e9-fe72-7cc49e8278dc.png" alt="" width="1200" height="611" loading="lazy"></p>
<p>そのまま「日本語」を選択します。<br><img src="/images/2024/20240606a/4ce1c615-1403-affc-1b94-a7bfcff1c364.png" alt="" width="1200" height="611" loading="lazy"></p>
<p>「日本語」を選択すると、確認をされますので「I Understand」を選択します。<br><img src="/images/2024/20240606a/49f6de95-4fc4-f09d-53f5-fb4a644b1ae4.png" alt="" width="1200" height="612" loading="lazy"></p>
<p>するとゲームが再起動され、スタート画面に戻ります。</p>
<p>この段階で「ゲーム開始」が日本語になっていれば成功です。<br>（英語表記のまま変わらない場合は、一度設定画面に移動し、スタート画面に戻るを行うと反映されることがあります）。</p>
<img src="/images/2024/20240606a/image_(10).png" alt="image_(10).png" width="1200" height="612" loading="lazy">

<p>ここまできたら準備完了です！</p>
<p>それでは実際にプレイの流れについて説明していきます！</p>
<h2 id="プレイの流れ">プレイの流れ</h2><p>AWS Cloud Questでは、街の中で困っている人達の課題をAWSのクラウドサービスを用いて解決していく中で、AWSクラウドの概念やセキュリティ、ユースケースやビジネスへの影響などについて学習することが出来ます。</p>
<p>実際にEC2のクエストを例に取って見ていきましょう。</p>
<h3 id="街の人に話しかける">街の人に話しかける</h3><p>街中で困っている人に話しかけます。</p>
<img src="/images/2024/20240606a/image_(11).png" alt="" width="1200" height="559" loading="lazy">

<p>困っている人の課題を聞き出します。<br>今回の依頼ではどうやら<strong>物理サーバーのハードディスクに障害が発生した</strong>ようです。<br><img src="/images/2024/20240606a/image_(12).png" alt="" width="1200" height="613" loading="lazy"></p>
<p>新たなハードドライブで代替すれば解決かと思いきや<br><strong>ハードドライブが届くのに48時間もかかってしまい、システムがすぐに復旧できない</strong>。<br><img src="/images/2024/20240606a/image_(18).png" alt="" width="1200" height="616" loading="lazy"></p>
<p>そこでソリューションとしてEC2を提案します。<br><img src="/images/2024/20240606a/image_(20).png" alt="" width="1200" height="607" loading="lazy"></p>
<p><strong>EC2を使えば数分で仮想サーバーを立てることが可能である</strong>と伝えます。<br><img src="/images/2024/20240606a/image_(21).png" alt="" width="1200" height="612" loading="lazy"><br>ここでクエストの受注が完了します。</p>
<p>一旦ここまでの事象・課題・ソリューションを整理します。</p>
<div class="scroll"><table>
<thead>
<tr>
<th>事象</th>
<th>物理サーバーのハードディスクに障害が発生した。</th>
</tr>
</thead>
<tbody><tr>
<td><strong>課題</strong></td>
<td>代替用のハードドライブが届くまでに時間がかかり、<strong>すぐにシステムが復旧できない。</strong></td>
</tr>
<tr>
<td><strong>ソリューション</strong></td>
<td><strong>仮想環境ですぐに立ち上げることができるEC2を導入する。</strong></td>
</tr>
</tbody></table></div>
<p>概要を把握したら、実際にサービスを使用して解決する段階に移っていきます。</p>
<h3 id="サービスを用いて解決">サービスを用いて解決</h3><p>ここでは <strong>「学習」「計画」「実践」「DIY」</strong> のフェーズに分かれてソリューションを構築していきます。</p>
<h4 id="学習">学習</h4><p>図と動画でソリューションに用いるサービスの学習ができます。<br>動画ではEC2とは、EC2に関わるその他サービス、その構成例などを学ぶことが出来ます。</p>
<div class="note-container note-info"><span class="note-icon"></span><div><p>情報量は結構多いですが、実践フェーズで用いる知識としては最低限で問題ないので完璧に理解しようとしなくても大丈夫です！</p></div></div>

<img src="/images/2024/20240606a/image.png" alt="" width="1200" height="596" loading="lazy">

<h4 id="計画">計画</h4><p>ソリューションの全体像を元に、実践フェーズとDIYフェーズの目標について事前に学びます。<br><img src="/images/2024/20240606a/image_2.png" alt="" width="1200" height="586" loading="lazy"></p>
<h4 id="実践">実践</h4><p>左下のステップを元に、実践を進めていきます。</p>
<p>「ラボを開始」を押すと環境がプロビジョニングされます。<br>その後「AWSコンソールを開く」を押すと、学習用のAWSアカウントからAWSコンソールに入ることができ、実際にサービスを構築できます。<br><img src="/images/2024/20240606a/image_3.png" alt="" width="1116" height="565" loading="lazy"><br>その後はステップの指示に従い、サービスを構築していきます。<br>（ここでは詳細な構築の流れはスキップします。気になった方はぜひプレイしてみてください）。</p>
<h4 id="DIY">DIY</h4><p>実践で得た知識をもとに、与えられた課題をクリアします。<br>EC2の場合は、「実践フェーズで起動したEC2インスタンスとは異なるアベイラビリティゾーンに、EC2インスタンスを起動しなさい」というものです。<br><img src="/images/2024/20240606a/image_(15).png" alt="" width="1200" height="582" loading="lazy"></p>
<p>実践での操作の意味が分かっていれば難なくクリアできます。<br>ここまでがクエストをプレイする大まかな流れになります！</p>
<h2 id="プレイしてみて感じたこと">プレイしてみて感じたこと</h2><p>これまでの説明からも分かる通り、AWS初学者にとってはとても学びになるサービスです。<br>初学者目線で良いと思った点、気になった点をそれぞれ挙げさせていただきます。</p>
<h3 id="良い点">良い点</h3><ul>
<li><strong>AWS を実際にコンソール操作しながら無料で学べる</strong><ul>
<li>AWS Cloud Questではラボ用のアカウントを用いることで、無料でサービスの構築が体験できます。<br>これにより実務に近い環境で学習ができるため、知識はあるけど使ったことが無い…という人にはとてもオススメです。</li>
</ul>
</li>
<li><strong>実践フェーズの説明や注意書きが親切</strong><ul>
<li>初めてAWSコンソールを触る人でも誤った操作をしないように、ワンスクロール、ワンクリック丁寧に解説してくれています。<br>これによりガイドに従っていればほとんどミスなくクリアできるでしょう。</li>
</ul>
</li>
</ul>
<div class="note-container note-info"><span class="note-icon"></span><div><p>こんな感じで作業の順番が明記されています<br><img src="/images/2024/20240606a/image_(17).png" alt="image_(17).png" width="1200" height="593" loading="lazy"></p></div></div>

<ul>
<li><strong>DIYフェーズの課題がいい感じの難易度</strong><ul>
<li>DIYフェーズでの課題は、実践フェーズの内容を理解していれば容易にクリアできる難易度だったので、「難しすぎて挫折してしまう…」なんてことが無かったのはとてもよかったです。</li>
</ul>
</li>
</ul>
<h3 id="気になった点">気になった点</h3><ul>
<li><strong>ガイドの画像が日本語対応されていない</strong><ul>
<li>AWSコンソールの作業画面は日本語対応されていますが、ガイドは英語のままになっています。<br>そのため、操作する際に適宜読み替える必要があるという点は少し気になりました。</li>
</ul>
</li>
<li><strong>サービスの説明がわかりにくい</strong><ul>
<li>英語から日本語に対応したということもあり、サービスの説明が若干遠回しで分かりにくいと感じる部分が多かったです。<br>そのため主要サービスの基礎知識がなんとなくわかってきたぞ、という方が実際の構築を学ぶツールとして用いるのが良いと思いました。</li>
</ul>
</li>
</ul>
<h2 id="まとめ">まとめ</h2><p>AWS初学者にとって、実際の構築の流れを体験できるというのはとても良い学びにつながると思いました。</p>
<p>今回はAWS Cloud Quest: Cloud Practitionerの説明でしたが、なんと2024年3月に <strong>「AWS Cloud Quest: Solutions Architect」</strong> も日本語対応されています（こちらは有料）。<br>（参考）</p>
<p>気になった方はぜひプレイしていただき、共にAWSライフを歩んでいきましょう！<br>最後まで読んでいただきありがとうございました。</p>
]]></content>
    <summary type="html">AWS Cloud Questの魅力や使い方、そして実際にプレイしてみた感想をAWS初学者の目線でお伝えします。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="AWS" scheme="https://future-architect.github.io/tags/AWS/"/>
    <category term="ネットワーク" scheme="https://future-architect.github.io/tags/Network/"/>
    <category term="初心者向け" scheme="https://future-architect.github.io/tags/%E5%88%9D%E5%BF%83%E8%80%85%E5%90%91%E3%81%91/"/>
  </entry>
  <entry>
    <title>LocustとGKEでスケーラブルな負荷テスト</title>
    <link href="https://future-architect.github.io/articles/20240216a/"/>
    <id>https://future-architect.github.io/articles/20240216a/</id>
    <published>2024-02-15T15:00:00.000Z</published>
    <updated>2024-02-15T15:00:00.000Z</updated>
    <author><name>岸下優介</name></author>
    <content type="html"><![CDATA[<h2 id="はじめに">はじめに</h2><p>本記事では、負荷テストツールであるLocustとGoogle Kubernetes Engine(GKE)と組み合わせて負荷テストを体感します。Kubernetesの柔軟なスケールアップ・ダウン能力によって、負荷の大きさを変えながらテストを行うことが可能となります。</p>
<p>参考：Google Kubernetes Engineを使用した負荷分散テスト</p>
<h2 id="Locustとは">Locustとは</h2><p>LocustはPythonベースで書かれたオープンソースの負荷テストツールとなります。<br>GitHub: https://github.com/locustio/locust</p>
<p>公式ページにも載っておりますが、特徴としては以下の3つになります。</p>
<ul>
<li>コードに基づいたユーザー挙動の定義<ul>
<li>ダサいUIや膨れ上がったXMLは必要無し</li>
<li>コードのみのわかりやすい記述が可能</li>
</ul>
</li>
<li>分散型でスケーラブル<ul>
<li>複数のマシンに分散された負荷テストの実行をサポート</li>
<li>数百万の同時ユーザーによるシミュレーションが可能</li>
</ul>
</li>
<li>歴戦の覇者（battle-tested）で実績がある<ul>
<li>GoogleやMicrosoft、AWSといった多くのユーザー（会社）がLocustを支持</li>
<li>Battlefield<sup id="fnref:1">1</sup>の戦績確認用Webアプリ開発時に負荷テストとして利用されたため、本当の意味でbattle-tested🤣</li>
</ul>
</li>
</ul>
<h2 id="構築">構築</h2><p>では早速、検証するための環境を構築していきます。必要なものは以下です。</p>
<ul>
<li>Google Cloud環境<ul>
<li>GKE</li>
<li>AppEngine</li>
<li>Artifact Registry</li>
</ul>
</li>
<li>ローカル環境<ul>
<li>gcloud</li>
<li>kubectl</li>
</ul>
</li>
</ul>
<p>インフラ側は全てTerraformを利用して構築しようと思います。<br>※ProjectやVPCの構築、gcloud、kubectlのインストールは割愛します。</p>
<h3 id="GKE">GKE</h3><p>GKEのTerraformコードは量が多いため、以下のリポジトリに配置しました。<br>https://github.com/bigface0202/terraform-useful-modules/tree/main/google-cloud<br>また、GKEを利用した検証に関するTIPSになりますが、GKEは立ち上げるまでに約20分少々かかるため、一番最初にGKEを構築しておくと検証がスムーズになります。</p>
<h3 id="AppEngine">AppEngine</h3><details><summary>Terraform</summary>

<figure class="highlight sh"><figcaption><span>app_engine.tf</span></figcaption><table><tr><td class="code"><pre><span class="line">resource <span class="string">&quot;google_app_engine_application&quot;</span> <span class="string">&quot;app&quot;</span> &#123;</span><br><span class="line">  project     = google_project.project_one.project_id</span><br><span class="line">  location_id = <span class="string">&quot;asia-northeast1&quot;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

</details>

<h3 id="Artifact-Registry">Artifact Registry</h3><details><summary>Terraform</summary>

<figure class="highlight sh"><figcaption><span>artifact_registry.tf</span></figcaption><table><tr><td class="code"><pre><span class="line">resource <span class="string">&quot;google_artifact_registry_repository&quot;</span> <span class="string">&quot;my-repo&quot;</span> &#123;</span><br><span class="line">  project       = google_project.project_one.project_id</span><br><span class="line">  location      = local.region</span><br><span class="line">  repository_id = <span class="string">&quot;my-repository&quot;</span></span><br><span class="line">  description   = <span class="string">&quot;example docker repository&quot;</span></span><br><span class="line">  format        = <span class="string">&quot;DOCKER&quot;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

</details>

<h3 id="デプロイ">デプロイ</h3><p>ここからはターミナルでの作業がメインとなるため、頻繁に利用する定数などを定義しておきます。適宜、自身で定義した内容に変更してください。</p>
<figure class="highlight shell"><figcaption><span>terminal</span></figcaption><table><tr><td class="code"><pre><span class="line">export PROJECT=test-project</span><br><span class="line">export REGION=asia-northeast1</span><br><span class="line">export AR_REPO=my-repository</span><br><span class="line">export LOCUST_IMAGE_NAME=locust-tasks</span><br><span class="line">export LOCUST_IMAGE_TAG=latest</span><br><span class="line">export SAMPLE_APP_TARGET=$&#123;PROJECT&#125;.appspot.com</span><br><span class="line">export GKE_CLUSTER_NAME=my-cluster</span><br></pre></td></tr></table></figure>

<p>AppEngineにデプロイするアプリケーションはGoogle Cloudが提供するサンプルアプリを利用します。</p>
<figure class="highlight bash"><figcaption><span>terminal</span></figcaption><table><tr><td class="code"><pre><span class="line"><span class="comment"># Clone the repository</span></span><br><span class="line">git <span class="built_in">clone</span> https://github.com/GoogleCloudPlatform/distributed-load-testing-using-kubernetes</span><br><span class="line"><span class="built_in">cd</span> distributed-load-testing-using-kubernetes</span><br><span class="line"></span><br><span class="line"><span class="comment"># Deploy the application</span></span><br><span class="line">gcloud app deploy sample-webapp/app.yaml --project=<span class="variable">$&#123;PROJECT&#125;</span></span><br></pre></td></tr></table></figure>

<p>App Engineへのデプロイが完了後、表示されたURLへ移動すると以下のような画面が表示されます。</p>
<img fetchpriority="high" src="/images/2024/20240216a/image.png" alt="image.png" width="1084" height="283">
<AppEngineの画面>

<p>次にGKEにLocustと負荷テスト用のタスクをデプロイしたいので、まずはLocustのイメージをビルドします。<br>各エンドポイント<code>/login</code>と<code>/metrics</code>に対して、1:999の割合で呼び出すようなタスクが定義されております。詳細は以下を参照してください。<br>docker-image&#x2F;locust-tasks&#x2F;tasks.py</p>
<figure class="highlight bash"><figcaption><span>terminal</span></figcaption><table><tr><td class="code"><pre><span class="line">gcloud builds submit \</span><br><span class="line">    --tag <span class="variable">$&#123;REGION&#125;</span>-docker.pkg.dev/<span class="variable">$&#123;PROJECT&#125;</span>/<span class="variable">$&#123;AR_REPO&#125;</span>/<span class="variable">$&#123;LOCUST_IMAGE_NAME&#125;</span>:<span class="variable">$&#123;LOCUST_IMAGE_TAG&#125;</span> \</span><br><span class="line">    docker-image</span><br></pre></td></tr></table></figure>

<p>Cloud Buildを利用することでイメージのビルドとプッシュがgcloudコマンド1回でできるので便利ですね。<br>イメージがちゃんとビルドできているかどうかをコンソールから確認してみましょう。<br><img src="/images/2024/20240216a/image_2.png" alt="image.png" width="1200" height="465" loading="lazy"></p>
<p>イメージのビルドができたのでデプロイしていきます。</p>
<figure class="highlight bash"><figcaption><span>terminal</span></figcaption><table><tr><td class="code"><pre><span class="line"><span class="comment"># Get cluster&#x27;s credential</span></span><br><span class="line">gcloud container clusters get-credentials <span class="variable">$&#123;GKE_CLUSTER&#125;</span> --region <span class="variable">$&#123;REGION&#125;</span> --project <span class="variable">$&#123;PROJECT&#125;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Check the connection</span></span><br><span class="line">kubectl get nodes</span><br><span class="line"><span class="comment"># Expected output below</span></span><br><span class="line"><span class="comment"># NAME                                                  STATUS   ROLES    AGE    VERSION</span></span><br><span class="line"><span class="comment"># gke-test-gke-cluster-test-gke-node-po-2165d20a-gztn   Ready    &lt;none&gt;   6m6s   v1.27.3-gke.100</span></span><br><span class="line"><span class="comment"># gke-test-gke-cluster-test-gke-node-po-7c71f952-7tvz   Ready    &lt;none&gt;   6m4s   v1.27.3-gke.100</span></span><br><span class="line"><span class="comment"># gke-test-gke-cluster-test-gke-node-po-f80380d5-4209   Ready    &lt;none&gt;   6m5s   v1.27.3-gke.100</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Deploy Locust</span></span><br><span class="line">envsubst &lt; kubernetes-config/locust-master-controller.yaml.tpl | kubectl apply -f -</span><br><span class="line">envsubst &lt; kubernetes-config/locust-worker-controller.yaml.tpl | kubectl apply -f -</span><br><span class="line">envsubst &lt; kubernetes-config/locust-master-service.yaml.tpl | kubectl apply -f -</span><br><span class="line"></span><br><span class="line"><span class="comment"># Check the deployment</span></span><br><span class="line">kubectl get pods</span><br><span class="line"><span class="comment"># Expected output below</span></span><br><span class="line"><span class="comment"># NAME                             READY   STATUS    RESTARTS   AGE</span></span><br><span class="line"><span class="comment"># locust-master-849c6b8799-j8hqt   1/1     Running   0          8m59s</span></span><br><span class="line"><span class="comment"># locust-worker-5466444784-8c474   1/1     Running   0          8m48s</span></span><br><span class="line"><span class="comment"># locust-worker-5466444784-b42l9   1/1     Running   0          8m53s</span></span><br><span class="line"><span class="comment"># locust-worker-5466444784-msw66   1/1     Running   0          8m45s</span></span><br><span class="line"><span class="comment"># locust-worker-5466444784-prrwg   1/1     Running   0          8m53s</span></span><br><span class="line"><span class="comment"># locust-worker-5466444784-rntx6   1/1     Running   0          8m53s</span></span><br></pre></td></tr></table></figure>

<p>初めて<code>envsubst</code>コマンドを知ったのですが、ターミナル上で定義済みの環境変数を代入出来て便利ですね。<br>無事にLocustをデプロイできたので、ポートフォワードして画面に接続してみます。</p>
<figure class="highlight bash"><figcaption><span>terminal</span></figcaption><table><tr><td class="code"><pre><span class="line">kubectl port-forward svc/locust-master-web -n default 8080:8089</span><br><span class="line"><span class="comment"># Expected output below</span></span><br><span class="line"><span class="comment"># Forwarding from 127.0.0.1:8080 -&gt; 8089</span></span><br><span class="line"><span class="comment"># Forwarding from [::1]:8080 -&gt; 8089</span></span><br></pre></td></tr></table></figure>

<p>http://127.0.0.1:8080/<br>にアクセスして、以下の画面が表示されることを確認します。<br><img src="/images/2024/20240216a/image_3.png" alt="image.png" width="1200" height="709" loading="lazy"></p>
<h2 id="負荷テストしてみる">負荷テストしてみる</h2><p>“Number of users”は負荷テストに利用するユーザーの同時接続数、”Spawn rate”は1秒当たりに何人のユーザーがリクエストを開始するかの数、Hostは接続先になります。<br>“Start swarming”を押すことでテストが開始されます。<br>以下の条件でテストを開始したときの画面が次のようになります。</p>
<ul>
<li>Number of users: 10</li>
<li>Spawn rate: 1<img src="/images/2024/20240216a/image_4.png" alt="image.png" width="1200" height="237" loading="lazy"></li>
</ul>
<p>右上のSTATUSの部分では現在接続中のユーザー数（5 Users）が表示されており、10Usersまで増えていきます。RPSはRequest Per Secondで、秒間のリクエスト数を表しております。<br>また、各種タブを切り替えることでテストに関する情報を見ることができます。</p>
<ul>
<li>Statistics<ul>
<li>Requestに対するレスポンスの統計情報</li>
<li>テストを行っているパスに対して個別にみることが可能</li>
</ul>
</li>
<li>Charts<ul>
<li>RPSやレスポンスタイムの時系列情報をグラフで確認することが可能</li>
</ul>
</li>
<li>Failures<ul>
<li>リクエストが失敗した場合に、どパスに対してどのMethod失敗したのか、エラーコードは何なのかを確認することが可能</li>
</ul>
</li>
<li>Exceptions<ul>
<li>例外発生時のTracebackを確認することが可能</li>
</ul>
</li>
<li>Current Ratio<ul>
<li>Locustのイメージビルド時にPythonファイルで設定した各パスに対するリクエスト数の割合を確認することが可能</li>
</ul>
</li>
<li>Download Data<ul>
<li>テスト結果をCSVやレポートとして出力可能</li>
</ul>
</li>
<li>Workers<ul>
<li>現在Locustを動作させているPodの数を確認可能</li>
</ul>
</li>
</ul>
<p>シンプルなUIの作りになっているため、直観的でわかりやすいです。<br>また、”Download Data”にてレポートを出力できるのですが、テスト結果に対して自動でサマリした状態で出力してくれるので非常に便利です。<br><img src="/images/2024/20240216a/image_5.png" alt="image.png" width="1200" height="735" loading="lazy"><br><img src="/images/2024/20240216a/image_6.png" alt="image.png" width="1200" height="897" loading="lazy"><br><img src="/images/2024/20240216a/image_7.png" alt="image.png" width="1200" height="776" loading="lazy"></p>
<p>また、かなり大きめの負荷をかけたい場合は、Podの数を増やすことで対応可能です。Kubernetesならではですね。<br>Podを増やしたい場合は以下のコマンドで増やします。</p>
<figure class="highlight bash"><figcaption><span>terminal</span></figcaption><table><tr><td class="code"><pre><span class="line">kubectl scale deployment/locust-worker --replicas=10</span><br></pre></td></tr></table></figure>

<h2 id="まとめ">まとめ</h2><p>本記事では、GKEとLocustを利用した分散型の負荷テストをハンズオン形式で紹介させていただきました。</p>
<p>Locustはシンプルな作りになっているため、特別なキャッチアップも必要なくサクッと使うことができます。</p>
<p>もしアプリのローンチを計画している方は、ローンチ前にLocustを利用した負荷テストをやってみてはいかがでしょうか？</p>
<div id="footnotes"><hr><div id="footnotelist"><ol style="list-style:none; padding-left: 0;"><li id="fn:1"><span style="vertical-align: top; padding-right: 10px;">1.</span><span style="vertical-align: top;">https://www.ea.com/ja-jp/games/battlefield</span> ↩</li></ol></div></div>]]></content>
    <summary type="html">負荷テストツールであるLocustとGKEを組み合わせて負荷テストを体感します。Kubernetesの柔軟なスケールアップ・ダウン能力によって、負荷の大きさを変えながらテストを行うことが可能となります。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="GKE" scheme="https://future-architect.github.io/tags/GKE/"/>
    <category term="GoogleCloud" scheme="https://future-architect.github.io/tags/GoogleCloud/"/>
    <category term="負荷テスト" scheme="https://future-architect.github.io/tags/%E8%B2%A0%E8%8D%B7%E3%83%86%E3%82%B9%E3%83%88/"/>
  </entry>
  <entry>
    <title>【合格記】Google Cloud Professional Developer認定資格を振り返る</title>
    <link href="https://future-architect.github.io/articles/20240117a/"/>
    <id>https://future-architect.github.io/articles/20240117a/</id>
    <published>2024-01-16T15:00:00.000Z</published>
    <updated>2024-01-16T15:00:00.000Z</updated>
    <author><name>岸下優介</name></author>
    <content type="html"><![CDATA[<img fetchpriority="high" src="/images/2024/20240117a/Professional_Level_Google_Meets_Background.png" alt="" width="1200" height="682">

<h2 id="はじめに">はじめに</h2><p>TIG岸下です。</p>
<p>Futureに中途で入社して今月で2年になります。2年前に初めてGoogle Cloudのプロジェクトに携わることになってから、ありがたいことに2年間Google Cloudに触れてきました。そこで、今回はDeveloper力を試すべくProfessional Developer認定資格を受験し、無事に合格を果たすことができました。</p>
<p>本記事では試験の特徴や学習内容、頻出しそうな項目について記していきたいと思います。</p>
<p>また本試験はGoogle Cloudパートナー企業向けのバウチャーを活用して受験しました。大変感謝しております！</p>
<p>Google Cloud 認定資格関連の過去記事：</p>
<p>【合格体験記】Google Cloudの入門試験：Cloud Digital Leader<br>【合格記】Google Cloud Professional Cloud Security Engineer認定資格を振り返る<br>【合格記】Google Cloud Professional Data Engineer認定資格を振り返る<br>【合格記】Google Cloud Professional Machine Learning Engineer認定資格を振り返る<br>Google Cloud Professional Cloud Architectの再認定に合格しました<br>GCP Professional Cloud Network Engineer に合格しました<br>GCP Associate Cloud Engineer 合格記</p>
<p>皆さんの協力のおかげで残りの合格記は…</p>
<ul>
<li>Cloud Database Engineer</li>
<li>Cloud DevOps Engineer</li>
<li>Google Workspace Administrator</li>
</ul>
<p>の3つのみとなり、非常に感慨深いです。</p>
<h2 id="試験と出題範囲">試験と出題範囲</h2><p>公式の出題範囲と、実際に自分が受けた際の所感は以下になります。</p>
<h3 id="スケーラビリティ、可用性、信頼性に優れたクラウドネイティブ-アプリケーションの設計">スケーラビリティ、可用性、信頼性に優れたクラウドネイティブ アプリケーションの設計</h3><ul>
<li>コンテナの基礎知識<ul>
<li>アプリケーションのコンテナ化におけるベストプラクティス</li>
</ul>
</li>
<li>アーキ設計とサービスの使い分け<ul>
<li>Cloud Run、Google Kubernetes Engine、App Engine、Managed Instance Groupなどアプリケーションのデプロイ環境</li>
<li>Cloud SQL、Spanner、Bigtable、Firebaseなどのデータベース環境</li>
<li>内部通信のみを利用したいケース（限定公開のGoogleアクセスを利用するなど）</li>
</ul>
</li>
<li>GKE（Kubernetes）の基礎知識<ul>
<li>Ingress、Service、Deployment、Podなどの役割、何を定義するのか</li>
<li>Workload Identityを利用したサービスアカウントとの紐づけ</li>
<li>Namespaceの使い分けにおけるベストプラクティス</li>
<li>Pod同士の通信方法</li>
<li>水平スケーリングと垂直スケーリング</li>
<li>Istio（Google CloudマネージドであればAnthos Service Mesh）</li>
</ul>
</li>
<li>PubSubの基礎知識<ul>
<li>トピックやサブスクリプションの置き方</li>
<li>トピックからPushされるのか、Pullするのか</li>
</ul>
</li>
</ul>
<h3 id="アプリケーションのデプロイ">アプリケーションのデプロイ</h3><ul>
<li>デプロイ方法の理解<ul>
<li>カナリアリリース、Blue&#x2F;Green、ローリングアップデートなど</li>
</ul>
</li>
<li>トラフィックの分割<ul>
<li>サービスそのものの機能としての分割（Cloud Runなど）、Kubernetesの機能としての分割</li>
</ul>
</li>
<li>デプロイタイミングの制御<ul>
<li>Cloud Buildを利用した自動化</li>
</ul>
</li>
</ul>
<h3 id="デプロイされたアプリケーションの管理">デプロイされたアプリケーションの管理</h3><ul>
<li>Cloud Loggingへのログ出力<ul>
<li>JSON形式による吐き出しの推奨</li>
<li>エラー標準出力を利用した連携</li>
</ul>
</li>
<li>Cloud Loggingの他サービスとの連携<ul>
<li>ログルーターを利用したPubSub、BigQuery、Cloud Storageとの連携</li>
<li>Google Cloud外のサービスと連携するにはPubSubにルーティングしておくなど</li>
</ul>
</li>
<li>Cloud Monitoringを利用したアラートの設定<ul>
<li>ログベースなのか、メトリクスベースなのか</li>
</ul>
</li>
<li>Cloud ProfilerやTraceを利用したエラーやサービス遅延の解明</li>
<li>権限回り<ul>
<li>最小権限の法則に従う</li>
<li>エラー内容から足りない権限のトラブルシューティング</li>
</ul>
</li>
</ul>
<h3 id="アプリケーションのビルドとテスト">アプリケーションのビルドとテスト</h3><ul>
<li>Cloud Buildを利用したイメージビルド<ul>
<li>Cloud Source Repositoryとの連携による自動化</li>
</ul>
</li>
<li>Artifact Registryを利用したイメージの脆弱性チェック<ul>
<li>Binary Authorization</li>
</ul>
</li>
<li>単体テストのベストプラクティス<ul>
<li>PubSubやCloud Runエミュレータを利用したローカルでのテスト</li>
</ul>
</li>
</ul>
<h3 id="Google-Cloud-サービスの統合">Google Cloud サービスの統合</h3><ul>
<li>オンプレとGoogle Cloudサービスの統合<ul>
<li>Kubernetesクラスターの共存</li>
</ul>
</li>
<li>リフトアンドシフト<ul>
<li>業務影響を最小に抑えた移行戦略</li>
<li>データベースとして利用されているアプリケーションを考慮した移行</li>
</ul>
</li>
</ul>
<h3 id="全体的な所感">全体的な所感</h3><p>やはりDeveloperということもあって、Google Cloudを利用したアプリケーション開発におけるベストプラクティスを問われる問題が多かったです。特に<strong>Kubernetesの基礎知識、GKEやCloud Runなど、アプリケーションをデプロイするためのサービスへの基礎知識</strong>は絶対に必要になります。<br>また、どの試験もあるあるな出題ですが、要求されるサービスがマネージドを希望しているのかどうか、可用性が重視されているのかなど、問いの文脈からサービスを選ぶ能力は必須です。<br>ただどの試験も4～5択なので、答えがわからなくても問いの文脈から消去法を使って選択肢を絞り込むことはできるので、サービスごとの違いを理解しておくと答えやすくなります。</p>
<h2 id="受験までの過程">受験までの過程</h2><p>出題範囲の内容はほとんど実務で経験済みだったので、勉強期間は1週間ほどで済みました。試験への理解度を測るために、毎度おなじみのUdemyで問題集を購入し、各模擬試験セットを2周しておきました。</p>
<p>詳解Google Professional Cloud Developer 模擬試験2024</p>
<h2 id="まとめ">まとめ</h2><p>Google Cloudのサービスは多岐にわたるため数が多く、存在を知らないサービスが結構あります。<br>今回受験してみて、Cloud ProfilerやCloud Traceというサービスの存在や利用用途を知ることができました。特にデプロイされたアプリケーションの関数毎でリソースに対する使用割合を計測できるCloud Profilerは今後使うことがでてきそうだなーと思いました。<br>また、デプロイ環境はほとんどのケースでまずCloud Runがファーストチョイスでいいのでは？ ってくらいCloud Runは便利なサービスだと試験内容を復習する中で感じました。</p>
<p>Cloud アーキテクチャセンターをベースにした問題も多く、ここらへんのドキュメントを1つずつハンズオンでやっていくと、更に理解を深められそうです。<br>Developer力を試したい方は一度受けてみてはいかがでしょうか！</p>
<p>アイキャッチ画像はGoogle Cloud Certificationから付与されたものになります。</p>
]]></content>
    <summary type="html">Developer力を試すべくProfessional Developer認定資格を受験し、無事に合格を果たすことができました。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="GoogleCloud" scheme="https://future-architect.github.io/tags/GoogleCloud/"/>
    <category term="合格記" scheme="https://future-architect.github.io/tags/%E5%90%88%E6%A0%BC%E8%A8%98/"/>
  </entry>
  <entry>
    <title>【合格体験記】Google Cloudの入門試験：Cloud Digital Leader</title>
    <link href="https://future-architect.github.io/articles/20231226a/"/>
    <id>https://future-architect.github.io/articles/20231226a/</id>
    <published>2023-12-25T15:00:00.000Z</published>
    <updated>2023-12-25T15:00:00.000Z</updated>
    <author><name>村上一彦</name></author>
    <content type="html"><![CDATA[<img fetchpriority="high" src="/images/2023/20231226a/IMG_6276.JPG" alt="IMG_6276.JPG" width="509" height="509">

<p>こんにちは。<br>公共サービス事業部の村上一彦です。</p>
<p>先日、Google Cloudの認定資格である「Cloud Digital Leader認定資格」を受験し、取得できました。</p>
<p>Cloud Digital Leader（CDL）認定資格の合格に至った学習過程について書いていきます。</p>
<h2 id="筆者のバックグラウンドについて">筆者のバックグラウンドについて</h2><p>大学は経営学部で、会計を中心に学んでおりました。その為、ITスキルはほぼゼロに等しい状況でした。</p>
<p>新卒から約3年ほど金融系システム(Java)の業務に従事、1年ほどAWSに触れる機会がありました。しかし、アプリ主体のチームに所属しており、インフラは別チームでしたので、機能を少し知っている程度です。その後、2020年にフューチャーに転職しましたが、クラウドに関わる経験はなく、クラウドに関する経験はほぼゼロの状況です。</p>
<p>他の資格としては、応用情報技術者試験を取得していますが、今回の試験にはほぼアドバンテージはないと思います。</p>
<h2 id="試験と出題範囲について">試験と出題範囲について</h2><p>Cloud Digital Leaderの試験は、Google Cloudの認定資格の中でも一番基礎的な試験として位置づけられています。<br>※ここから公式サイトの抜粋を引用しています。<br>https://cloud.google.com/learn/certification/cloud-digital-leader?hl=ja</p>
<h3 id="推奨される経験">推奨される経験</h3><blockquote>
<p>技術専門家と連携した経験<br>技術的な前提条件はありません。</p>
</blockquote>
<p>自身が技術専門家として従事した業務経験を前提としていない為、私のようにインフラやクラウドが未経験の人でも目指せる資格ということがわかります。</p>
<h3 id="試験の形式">試験の形式</h3><blockquote>
<p>試験時間: 90 分<br>登録料: $99<br>言語: 英語、日本語</p>
</blockquote>
<h3 id="出題範囲">出題範囲</h3><div class="scroll"><table>
<thead>
<tr>
<th align="left">内容</th>
<th align="center">配点</th>
</tr>
</thead>
<tbody><tr>
<td align="left">Google Cloud によるデジタル トランスフォーメーション</td>
<td align="center">10%</td>
</tr>
<tr>
<td align="left">データと Google Cloud によるイノベーション</td>
<td align="center">30%</td>
</tr>
<tr>
<td align="left">インフラストラクチャとアプリケーションのモダナイゼーション</td>
<td align="center">30%</td>
</tr>
<tr>
<td align="left">Google Cloud のセキュリティとオペレーション</td>
<td align="center">30%</td>
</tr>
</tbody></table></div>
<p>ざっくり言うと、Google Cloudで提供している各機能の内容と、導入するメリットなどがメインの内容です。</p>
<h2 id="学習過程">学習過程</h2><h3 id="1-「図解即戦力-Google-Cloudのしくみと技術がこれ1冊でしっかりわかる教科書」の読了">1. 「図解即戦力 Google Cloudのしくみと技術がこれ1冊でしっかりわかる教科書」の読了</h3><p>私は、Google Cloudについての予備知識が全くなかったため、まず入門書の「図解即戦力 Google Cloudのしくみと技術がこれ1冊でしっかりわかる教科書」を読みました。</p>
<p>この本については、他の方が詳しく紹介されていますので、ぜひお読みいただければと思います。</p>
<blockquote>
<p>フューチャー技術ブログ「Google Cloudのしくみと技術がしっかりわかる教科書を読んだ感想」<br>https://future-architect.github.io/articles/20230302a/</p>
</blockquote>
<p>こちらの本は入門書なので読みやすかったです。試験の対策としては、一部カバーしていない部分はありますが、次で紹介する模擬試験でカバーできるので、問題ありませんでした。</p>
<p>模擬試験がメインの試験対策になるため、本の内容は熟読せずに流し読みでも問題ないです。私は１周流し読みしました。4時間くらいかかりました（細かい記載は飛ばしました）。</p>
<h3 id="2-Udemyの模擬試験の反復">2. Udemyの模擬試験の反復</h3><p>Udemyにて、こちらの模擬試験を購入し反復しました。</p>
<blockquote>
<p>GCP：Google Cloud Digital Leader模擬試験問題集（6回分320問）<br>https://www.udemy.com/course/google-cloud-digital-leader6320/</p>
</blockquote>
<p>模擬試験は6回分収録されていますが、私は勉強時間が取れず、5回までを2周しました。</p>
<p>1周目を解いた後、模擬試験の解説をしっかり読み、わからない箇所については、先述の入門書に戻ったりもしました。そのように振り返りをすることで、1周目は40～50点でしたが、2周目では80点以上を取れるようになりました。</p>
<p>おすすめはできませんが、正直、理解を後回しにして、模擬試験の繰り返し学習で、反射的に問題を解けるようになるだけで、合格点を出せるのではないかと思います。</p>
<p>見直し時間も含め、20時間くらいかかりました。</p>
<h4 id="模擬試験のいい点">模擬試験のいい点</h4><ul>
<li>本試験の内容をカバーしている。</li>
<li>本試験と似たような形式で出題される。</li>
<li>解説が非常によく、間違いの選択肢がなぜ誤りかも書いてあるため、腕試しという意味よりも、インプット学習に使用できる内容でした。</li>
</ul>
<h4 id="コツ">コツ</h4><ul>
<li>各サービスとキーワードの組み合わせを覚える。</li>
<li>メインの機能がどのように拡張できるか(できないか)を理解する。</li>
<li>非推奨サービスは正答にならない。(経験則)</li>
<li>計算問題は答えを覚える（理由は後述）</li>
</ul>
<h2 id="試験当日">試験当日</h2><p>試験は近くのテストセンターで受験しました。</p>
<p><strong>ここで問題だったのが、会場内に筆記用具が持ち込めず（貸し出しもNG）、計算問題を暗算でやるしかありませんでした。</strong></p>
<p>試験時間は30分以上残して終了しましたので、時間配分はそれほど意識しなくても問題ないと思います。</p>
<h2 id="さいごに">さいごに</h2><p>初めてのGoogle Cloudの認定資格の試験でしたが、業務経験を問わず、丁度いい内容と難易度だと思いました。試験内容が技術に寄りすぎておらず、「Google Cloudにはどんなメリットがあるか」ということを理解できたので、私のように、インフラエンジニアではない人にも、生かしていける知識だと思いました。</p>
<p>また、AWSやAzureなど、他のクラウドサービスにもGoogle Cloudにあるような機能がある為、クラウド全般の入門としてもいいと思いました。</p>
<p>これからクラウドの知識やインフラの知識を身に着けたい人のスタートに良い試験だと思います。ぜひ受験してみてください！</p>
]]></content>
    <summary type="html">Google Cloudの認定資格であるCloud Digital Leader認定資格を受験し、取得することができました。Cloud Digital Leader認定資格の合格に至った学習過程について書いていこうと思います。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="CDL" scheme="https://future-architect.github.io/tags/CDL/"/>
    <category term="GoogleCloud" scheme="https://future-architect.github.io/tags/GoogleCloud/"/>
    <category term="合格記" scheme="https://future-architect.github.io/tags/%E5%90%88%E6%A0%BC%E8%A8%98/"/>
  </entry>
  <entry>
    <title>VPC外からCloud SQL Auth Proxyを利用したPrivate IP Cloud SQLへの接続</title>
    <link href="https://future-architect.github.io/articles/20231019a/"/>
    <id>https://future-architect.github.io/articles/20231019a/</id>
    <published>2023-10-18T15:00:00.000Z</published>
    <updated>2023-10-18T15:00:00.000Z</updated>
    <author><name>岸下優介</name></author>
    <content type="html"><![CDATA[<h2 id="はじめに">はじめに</h2><p>本記事では、Private IPしか持たないCloud SQLへ接続する方法として、Cloud SQL Auth Proxyを利用した接続方法について紹介致します。</p>
<h2 id="Cloud-SQL">Cloud SQL</h2><p>Cloud SQLはMy SQL、PostgreSQL、SQL Server用のフルマネージドリレーショナルデータベースのサービスです。</p>
<p>Google Cloudには、AlloyDB、Spanner、Firestore、Bigtableなど様々なデータベースサービスが存在しますが、Cloud SQLもその内の1つになります。たくさんあってどれ選べばいいのかわからない！ という状況に陥った場合は、Your Google Cloud database options, explainedからベストプラクティスを探るのが良いと思います。</p>
<h3 id="Cloud-SQLへの接続方法">Cloud SQLへの接続方法</h3><p>Cloud SQLへは<code>mysql</code>や<code>psql</code>コマンドなどで接続でき、接続方法として以下の2つの方法が用意されています。</p>
<ol>
<li>プライベートIPアドレス<ul>
<li>同一VPCから接続できる内部接続</li>
</ul>
</li>
<li>パブリックIPアドレス<ul>
<li>インターネット経由でアクセスできる外部接続</li>
</ul>
</li>
</ol>
<p>SQLインスタンスをインターネット上に晒したくないというセキュアな条件を満たしたい場合は、1のプライベートIPアドレスのみを利用するケースが多いかと思われます。但し、上記で記載した通り同一VPC内からの接続となるため、</p>
<ol>
<li>接続元となるPC・VMをそのVPC内に構築する必要</li>
<li>もしくはそのVPC内へのアクセス経路を持つ必要</li>
</ol>
<p>があります。<br>1の場合は、Cloud SQLインスタンスのプライベートIPに対して直接接続できるので一番手っ取り早い方法かと思います。</p>
<img fetchpriority="high" src="/images/2023/20231019a/image.png" alt="image.png" width="782" height="550">

<p>2の場合は、Cloud SQLが存在するVPC内へアクセス経路を持つ必要があるため、VPC PeeringやCloud VPN、Cloud Interconnectによって接続元が利用するVPCがお互いに経路を確保し、Cloud SQLのPrivate IPが広報される必要があります。<br>※本記事ではHA-VPN構成を例に取り扱わせて頂きます。</p>
<img src="/images/2023/20231019a/image_2.png" alt="image.png" width="1200" height="394" loading="lazy">

<p>但し、Cloud SQLのプライベートIPアドレスが既に割り振られている場合、広報先のVPC内でそのIPアドレスが既に使われている場合は多々あります。そのような状況で広報をしてしまうと、IPアドレスが被ってしまい広報できない、もしくはネットワーク事故につながることになります。さて、この場合どうしましょう🤔</p>
<h3 id="Cloud-SQL-Auth-Proxy">Cloud SQL Auth Proxy</h3><p>ここで出番となるのが、Cloud SQL Auth Proxyです。公式では「Cloud SQL Auth Proxyは承認済みネットワークやSSLの構成を必要とせず、安全にインスタンスにアクセスできるCloud SQLコネクタです」とあり、Auth Proxy経由でCloud SQLインスタンスへ接続できるようになります。また、認可にIAM権限を利用することになるため、よりセキュアな接続となります。</p>
<p>このCloud SQL Auth Proxyを利用して、Cloud SQLインスタンスが存在するVPC内外から接続経路を構築していきます。</p>
<h2 id="Cloud-SQL-Auth-Proxyを利用した接続">Cloud SQL Auth Proxyを利用した接続</h2><img src="/images/2023/20231019a/image_3.png" alt="image.png" width="1200" height="397" loading="lazy">

<p>アーキテクチャ上で変わった部分としては黄色の箇所で、Cloud SQLインスタンスが存在するVPC-AにCloud SQL Auth Proxyを立てておくためのDB Bastion VMを構築しておく必要があります。また、Cloud SQLインスタンスは複数あることを想定しております。</p>
<p>HA VPNの構築は公式のドキュメントにお任せします。公式がTerraformの例まで用意しているのは非常にありがたいですね。</p>
<ul>
<li>HA VPN ゲートウェイを作成して VPC ネットワークに接続する</li>
<li>HA VPN ゲートウェイ向けの Terraform の例</li>
</ul>
<p>HA VPN構築後、DB Bastionで利用するサブネットワークのIPアドレス範囲をVPC-B側に広報することを忘れないように気を付けましょう。</p>
<p>また、VPC-B側のVMの構築、VPC-A側のCloud SQLの構築についても省略させて頂きます。<br>以下のTerraform公式が参考になると思います。</p>
<ul>
<li>Compute Engine</li>
<li>Cloud SQL - Private IP Instance</li>
</ul>
<p>DB Bastion VMについてですが、Startup ScriptにてCloud SQL Auth Proxyをsystemdとして起動するように設定しておくと、起動時に確実にAuth Proxyが起動され、更に状態を管理しやすくなります。</p>
<p>以下にそのStartup Scriptを記載します。</p>
<p>※最新ver.は公式からチェックしてください。</p>
<figure class="highlight bash"><figcaption><span>cloudsql_auth_proxy_setup.sh</span></figcaption><table><tr><td class="code"><pre><span class="line"><span class="comment"># Define your variables</span></span><br><span class="line">PROJECT_ID=test_pj</span><br><span class="line"><span class="built_in">declare</span> -a INSTANCES=(<span class="string">&quot;test-db1&quot;</span> <span class="string">&quot;test-db2&quot;</span>)</span><br><span class="line"><span class="built_in">declare</span> -a REGIONS=(<span class="string">&quot;asia-northeast1&quot;</span> <span class="string">&quot;asia-northeast2&quot;</span>)</span><br><span class="line"><span class="built_in">declare</span> -a PORTS=(<span class="string">&quot;5432&quot;</span> <span class="string">&quot;5433&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># Download Cloud SQL Auth Proxy from the bucket and isntall</span></span><br><span class="line">curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.6.1/cloud-sql-proxy.linux.amd64</span><br><span class="line"><span class="built_in">mv</span> cloud-sql-proxy /usr/local/bin/</span><br><span class="line"><span class="built_in">chmod</span> +x /usr/local/bin/cloud-sql-proxy</span><br><span class="line"></span><br><span class="line"><span class="comment"># Create systemd service for each Cloud SQL instance</span></span><br><span class="line"><span class="keyword">for</span> index <span class="keyword">in</span> <span class="variable">$&#123;!INSTANCES[*]&#125;</span></span><br><span class="line"><span class="keyword">do</span></span><br><span class="line">  instance=<span class="variable">$&#123;INSTANCES[$index]&#125;</span></span><br><span class="line">  region=<span class="variable">$&#123;REGIONS[$index]&#125;</span></span><br><span class="line">  port=<span class="variable">$&#123;PORTS[$index]&#125;</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># Create a systemd service file</span></span><br><span class="line">  <span class="built_in">sudo</span> bash -c <span class="string">&quot;cat &lt;&lt;EOF &gt; /etc/systemd/system/cloud-sql-proxy-<span class="variable">$&#123;instance&#125;</span>.service</span></span><br><span class="line"><span class="string">[Unit]</span></span><br><span class="line"><span class="string">Description=Google Cloud SQL Auth Proxy <span class="variable">$&#123;instance&#125;</span></span></span><br><span class="line"><span class="string">After=network.target</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">[Service]</span></span><br><span class="line"><span class="string">ExecStart=/usr/local/bin/cloud-sql-proxy --address 0.0.0.0 --private-ip <span class="variable">$&#123;PROJECT_ID&#125;</span>:<span class="variable">$&#123;region&#125;</span>:<span class="variable">$&#123;instance&#125;</span> --port <span class="variable">$&#123;port&#125;</span></span></span><br><span class="line"><span class="string">Restart=always</span></span><br><span class="line"><span class="string">User=root</span></span><br><span class="line"><span class="string">Type=simple</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">[Install]</span></span><br><span class="line"><span class="string">WantedBy=multi-user.target</span></span><br><span class="line"><span class="string">EOF&quot;</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># Enable and start the service</span></span><br><span class="line">  <span class="built_in">sudo</span> systemctl <span class="built_in">enable</span> cloud-sql-proxy-<span class="variable">$&#123;instance&#125;</span>.service</span><br><span class="line">  <span class="built_in">sudo</span> systemctl start cloud-sql-proxy-<span class="variable">$&#123;instance&#125;</span>.service</span><br><span class="line"><span class="keyword">done</span></span><br></pre></td></tr></table></figure>

<p>ここで気を付けたいのがCloud SQL Auth Proxyの実行コマンドで<code>--address</code>を指定する際に、<code>127.0.0.1</code>と指定してしまうとlocalhostからの接続しか受け付けなくなってしまいます。今回はDB Bastion外から接続する必要があるため、<code>0.0.0.0</code>で指定しております。</p>
<p>作成したStartup scriptはDB Bastion VM構築時に<code>startup-script</code>として指定しましょう。<br>また、ネットワークタグ：<code>tags</code>も設定しておきます。</p>
<figure class="highlight sh"><figcaption><span>compute_instance.tf</span></figcaption><table><tr><td class="code"><pre><span class="line">resource <span class="string">&quot;google_compute_instance&quot;</span> <span class="string">&quot;db_bastion&quot;</span> &#123;</span><br><span class="line"><span class="comment"># ...</span></span><br><span class="line"></span><br><span class="line">    tags = [<span class="string">&quot;db-bastion&quot;</span>]</span><br><span class="line"><span class="comment"># ...</span></span><br><span class="line"></span><br><span class="line">    metadata = &#123;</span><br><span class="line">        startup-script = <span class="string">&quot;startup-scripts/cloudsql_auth_proxy_setup.sh&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line"><span class="comment">#...</span></span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>DB上のデータ外部持ち出しを防ぐためにDB BastionのEGRESSを全て拒否しているケースもあると思います。その場合、Cloud SQL Auth Proxy用に<strong>Cloud SQLインスタンスのプライベートIPアドレスに対してPort:3307を介したEGRESSを許可</strong>するFirewallを設定しておく必要があります。</p>
<p>参考：Cloud SQL Auth Proxyの接続経路</p>
<figure class="highlight sh"><figcaption><span>compute_firewall.tf</span></figcaption><table><tr><td class="code"><pre><span class="line">resource <span class="string">&quot;google_compute_firewall&quot;</span> <span class="string">&quot;db_bastion2cloudsql&quot;</span> &#123;</span><br><span class="line">  name               = <span class="string">&quot;db-bastion2cloudsql&quot;</span></span><br><span class="line">  network            = &lt;YOUR_VPC_NAME&gt;</span><br><span class="line">  direction          = <span class="string">&quot;EGRESS&quot;</span></span><br><span class="line">  target_tags        = [<span class="string">&quot;db-bastion&quot;</span>]</span><br><span class="line">  destination_ranges = [</span><br><span class="line">    google_sql_database_instance.instance1.ip_address.0.ip_address,</span><br><span class="line">    google_sql_database_instance.instance2.ip_address.0.ip_address,</span><br><span class="line">  ]</span><br><span class="line"></span><br><span class="line">  allow &#123;</span><br><span class="line">    protocol = <span class="string">&quot;tcp&quot;</span></span><br><span class="line">    ports    = [<span class="string">&quot;3307&quot;</span>]</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>※<code>google_sql_database_instance.instance1</code>, <code>google_sql_database_instance.instance2</code>というリソース名でCloud SQLインスタンスを構築していることを想定しております。</p>
<p>また、Cloud SQL Auth Proxyのセクションでも述べましたがIAM権限を利用した認可となるため、以下の権限をDB BastionのService Accountへ設定する必要があります。</p>
<ul>
<li>roles&#x2F;cloudsql.client</li>
</ul>
<p>これで構築・設定は完了となります。試しにCloud SQLにPostgreSQLを設定し、VPC Bのインスタンスからpsqlコマンドで接続してみます。</p>
<figure class="highlight bash"><figcaption><span>terminal</span></figcaption><table><tr><td class="code"><pre><span class="line">psql <span class="string">&quot;host=&lt;DB Bastion&#x27;s IP address&gt; port=5432 dbname=test_db sslmode=disable user=test_user password=****&quot;</span></span><br><span class="line">psql (12.15 (Ubuntu 12.15-0ubuntu0.20.04.1), server 13.10)</span><br><span class="line">WARNING: psql major version 12, server major version 13.</span><br><span class="line">         Some psql features might not work.</span><br><span class="line">Type <span class="string">&quot;help&quot;</span> <span class="keyword">for</span> <span class="built_in">help</span>.</span><br><span class="line">postgres=&gt;</span><br></pre></td></tr></table></figure>

<p>無事に接続できました！</p>
<h2 id="まとめ">まとめ</h2><p>本記事ではプライベートIPしか持たないCloud SQLインスタンスに対して、インスタンスが存在するVPCの外からCloud SQL Auth Proxyを介して接続する方法を紹介しました。</p>
<p>Cloud SQL Auth Proxy自体、全くキャッチアップなく簡単に使えて非常に便利なサービスです。Cloud SQL Auth Proxy Docker イメージを使用した SQL サーバー クライアントの接続で説明されているようにDockerとして起動もできるので、自身の要件に合わせて構成してみて下さい。</p>
]]></content>
    <summary type="html">Private IPしか持たないCloud SQLへ接続する方法として、Cloud SQL Auth Proxyを利用した接続方法について紹介致します。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="CloudSQL" scheme="https://future-architect.github.io/tags/CloudSQL/"/>
    <category term="GoogleCloud" scheme="https://future-architect.github.io/tags/GoogleCloud/"/>
    <category term="IAM" scheme="https://future-architect.github.io/tags/IAM/"/>
    <category term="VPC" scheme="https://future-architect.github.io/tags/VPC/"/>
    <category term="プロキシ" scheme="https://future-architect.github.io/tags/%E3%83%97%E3%83%AD%E3%82%AD%E3%82%B7/"/>
  </entry>
  <entry>
    <title>stree：S3バケットをtreeするCLIコマンド</title>
    <link href="https://future-architect.github.io/articles/20230926a/"/>
    <id>https://future-architect.github.io/articles/20230926a/</id>
    <published>2023-09-25T15:00:00.000Z</published>
    <updated>2023-09-25T15:00:00.000Z</updated>
    <author><name>宮永崇史</name></author>
    <content type="html"><![CDATA[<img fetchpriority="high" src="/images/2023/20230926a/stree-display.png" alt="" width="1200" height="600">

<h2 id="はじめに">はじめに</h2><p>こんにちは。TIG&#x2F;EXユニット所属の宮永です。</p>
<p>本記事ではS3バケットをtreeするCLIコマンドを紹介します。</p>
<p>クラスメソッドさんの記事(S3 バケットの中身を tree 形式で表示してくれる s3-tree を Amazon Linux 2 にインストールして使ってみた)を拝見して、s3-treeというツールの存在を知ったのですが、profileを指定できなかったり、バケット単位でしか指定できなかったりと細かな部分で不自由さを感じたためGoでCLIツールを作成しました。</p>
<p>作成したツールは以下リンク先で公開しています。</p>
<p><img src="https://gh-card.dev/repos/orangekame3/stree.svg" alt="orangekame3/stree - GitHub"></p>
<blockquote>
<p>streeは「エスツリー」と読みます。先に語感の良い名称を思いついたため、衝動に身を任せて開発しました。</p>
</blockquote>
<h2 id="機能概要">機能概要</h2><p>まずは利用画面を見ていただいたほうがイメージ付きやすいかと思いますのでgif画像を添付します。</p>
<img src="/images/2023/20230926a/demo.gif" alt="demo" width="1200" height="686" loading="lazy">

<p>streeは以下の機能をサポートしています。</p>
<ul>
<li>バケット名、プレフィックス名指定によるtree表示</li>
<li>プロファイル、リージョンの指定</li>
<li>LocalStack上のS3バケットのtree表示</li>
<li>カラー表示（オプションで無効化も可能です）</li>
</ul>
<h2 id="インストール方法">インストール方法</h2><p>GoとHomebrew経由でインストール可能です。</p>
<p>各種ビルド済みのバイナリも公開しているのでReleaseから手動インストールもできます。</p>
<h3 id="Goによるインストール">Goによるインストール</h3><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">go install github.com/orangekame3/stree@latest</span><br></pre></td></tr></table></figure>

<h3 id="Homebrewによるインストール">Homebrewによるインストール</h3><figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">brew install orangekame3/tap/stree</span><br></pre></td></tr></table></figure>

<h2 id="使い方">使い方</h2><div class="note-container note-warn"><span class="note-icon"></span><div><p><strong>前提</strong><br>aws cliで利用するconfig及びcredentialsは事前に設定しておく必要があります。</p></div></div>

<p>以降、configとcredentialsが以下の通り設定されているものとします。</p>
<figure class="highlight ini"><figcaption><span>~/.aws/config</span></figcaption><table><tr><td class="code"><pre><span class="line"><span class="section">[my_profile]</span></span><br><span class="line"><span class="attr">region</span> = ap-northeast-<span class="number">1</span></span><br><span class="line"><span class="attr">output</span> = json</span><br></pre></td></tr></table></figure>

<figure class="highlight ini"><figcaption><span>~/.aws/credentials</span></figcaption><table><tr><td class="code"><pre><span class="line"><span class="section">[my_profile]</span></span><br><span class="line"><span class="attr">aws_access_key_id</span>=XXXXXXXXXXXXXXXXXXXXX</span><br><span class="line"><span class="attr">aws_secret_access_key</span>=XXXXXXXXXXXXXXXXX</span><br></pre></td></tr></table></figure>

<h3 id="基本的なコマンド">基本的なコマンド</h3><p>バケット名とprofileを指定して、以下のコマンドを実行します。</p>
<p>プロファイルは<code>--profile(-p)</code>で指定します。</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">stree my-bucket -p my_profile</span><br></pre></td></tr></table></figure>

<p>以下のような出力が得られます。</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">my-bucket</span><br><span class="line">└── <span class="built_in">test</span></span><br><span class="line">    ├── dir1</span><br><span class="line">    │   ├── dir1_1</span><br><span class="line">    │   │   └── dir1_1_1</span><br><span class="line">    │   │       ├── file1.csv</span><br><span class="line">    │   │       └── file2.csv</span><br><span class="line">    │   └── dir1_2</span><br><span class="line">    │       ├── file1.csv</span><br><span class="line">    │       ├── file2.csv</span><br><span class="line">    │       └── file3.csv</span><br><span class="line">    ├── dir2</span><br><span class="line">    │   └── dir2_1</span><br><span class="line">    │       └── dir2_1_1</span><br><span class="line">    │           ├── file1.csv</span><br><span class="line">    │           ├── file2.csv</span><br><span class="line">    │           └── file3.csv</span><br><span class="line">    └── dir3</span><br><span class="line">        ├── file1.csv</span><br><span class="line">        └── file2.csv</span><br><span class="line"></span><br><span class="line">9 directories, 10 files</span><br></pre></td></tr></table></figure>

<h3 id="プレフィックスを指定">プレフィックスを指定</h3><p>通常のユースケースを考えると、バケットの中には大量のオブジェクトが存在していることが予想されます。</p>
<p>そのため、バケット指定しかできない状況では使い物になりません。バケット名に続けてprefixを指定することで、ユーザーが確認したいパスの情報のみを確認できます。</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">stree my-bucket/test/dir2 -p my_profile</span><br></pre></td></tr></table></figure>

<p>このコマンドの実行結果は以下のようになります。</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">my-bucket</span><br><span class="line">└── <span class="built_in">test</span></span><br><span class="line">    └── dir2</span><br><span class="line">        └── dir2_1</span><br><span class="line">            └── dir2_1_1</span><br><span class="line">                ├── file1.csv</span><br><span class="line">                ├── file2.csv</span><br><span class="line">                └── file3.csv</span><br><span class="line"></span><br><span class="line">4 directories, 3 files</span><br></pre></td></tr></table></figure>

<h3 id="リージョンのオーバーライド">リージョンのオーバーライド</h3><p><code>--region(-r)</code>でリージョンを指定できます。</p>
<p>profileに記載しているリージョンとは別のリージョンを指定したいときなどは<code>--region</code>フラグを利用してオーバーライドしてください。</p>
<h3 id="Localstackでの利用">Localstackでの利用</h3><p>Localstackでも利用できます。</p>
<p>ローカルスタックで利用する場合、endpointとregionはデフォルトで以下の通り設定していると思います。</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">endpoint = http://localhost:4566</span><br><span class="line">region = us-east-1</span><br></pre></td></tr></table></figure>

<p>大多数の場合は↑の設定で利用しているかと思いますのでLocalstack用のフラグを追加しています。<code>--local(-l)</code>がそれです。</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">stree my-bucket/test/dir2 -l</span><br></pre></td></tr></table></figure>

<p>特別な事情でエンドポイントやリージョンを変更する場合もあるかと思いますので、<code>--region(-r)</code> フラグと<code>--endpoint(-e)</code>でもオーバーライドできます。</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">stree my-bucket/test/dir2 -r us-east-1 -e http://localhost:4537</span><br></pre></td></tr></table></figure>

<p>出力は同じであるため省略します。</p>
<h3 id="カラー出力を無効化">カラー出力を無効化</h3><p><code>--no-color(-n)</code>でカラー出力を無効化できます。</p>
<p>▼カラーつき<br><img src="/images/2023/20230926a/color.png" alt="color.png" width="479" height="391" loading="lazy"></p>
<p>▼カラーなし<br><img src="/images/2023/20230926a/no-color.png" alt="no-color.png" width="504" height="391" loading="lazy"></p>
<h2 id="さいごに">さいごに</h2><p>実装に取り掛かるうえでtreeは骨が折れそうだなと思ったのですが、既にgteeというパッケージがGitHubで公開されていました。</p>
<p><img src="https://gh-card.dev/repos/ddddddO/gtree.svg" alt="ddddddO/gtree - GitHub"></p>
<p>パッケージの利用方法なども記事で公開されていて実装に困ることはありませんでした。</p>
<p>▼参考</p>
<ul>
<li>Markdown形式の入力からtreeを出力するCLI</li>
<li>Goでtreeを表現する</li>
<li>Markdown形式の入力からファイル&#x2F;ディレクトリを生成するCLI&#x2F;Goパッケージ</li>
</ul>
<p>また、gtreeの作者である@ddddddOさんにはstreeにissueを起票いただいており、本記事公開前に致命的なバグを修正できました。ありがとうございます。</p>
<p>gtreeでstreeの機能の核は難なく実装できたため、着想から実装完了まで１日もかかりませんでした。</p>
<p>S3をtreeしてみたくなったらぜひstreeを利用してみてください。</p>
<p>本記事をお読みいただきありがとうございました。</p>
]]></content>
    <summary type="html">S3バケットをtreeするCLIコマンドを紹介します。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="AWS" scheme="https://future-architect.github.io/tags/AWS/"/>
    <category term="CLI" scheme="https://future-architect.github.io/tags/CLI/"/>
    <category term="Go" scheme="https://future-architect.github.io/tags/Go/"/>
    <category term="OSS" scheme="https://future-architect.github.io/tags/OSS/"/>
    <category term="S3" scheme="https://future-architect.github.io/tags/S3/"/>
  </entry>
  <entry>
    <title>GCP Pub/Subの概念をかみ砕いて説明してみた</title>
    <link href="https://future-architect.github.io/articles/20230613a/"/>
    <id>https://future-architect.github.io/articles/20230613a/</id>
    <published>2023-06-12T15:00:00.000Z</published>
    <updated>2023-06-12T15:00:00.000Z</updated>
    <author><name>添田瑛介</name></author>
    <content type="html"><![CDATA[<h2 id="はじめに">はじめに</h2><p>はじめまして。2023年1月キャリア入社の添田です。1月から参画させていただいているプロジェクトでGoogle Cloud PlatformのPubSub(以降PubSub)を使用して開発することになり、苦戦した部分が多々ありました。そこで今回はPubSubについて噛み砕いて説明していきます。今後PubSubを使用した開発をする方の助けになれればと思います。</p>
<p>(Google Cloud Platform PubSubについての公式ドキュメントはこちらです。)</p>
<h3 id="1-そもそもPubSubとは何か">1. そもそもPubSubとは何か</h3><p>PubSubとは、非同期型のメッセージングサービスです。つまり、異なるコンポーネントやアプリケーション間でデータを非同期的に送受信するためのシステムになります。</p>
<p>補足ですが、他のクラウドベンダーでも類似したメッセージングサービスが提供されています。選択するメッセージングサービスはその時の要件等に合わせて検討していきましょう。</p>
<ul>
<li>AWS<ul>
<li>Amazon Simple Queue Service（Amazon SQS）</li>
<li>Amazon Kinesis Data Streams</li>
</ul>
</li>
<li>Azure<ul>
<li>Azure Service Bus: Service Bus</li>
<li>Azure Event Grid: Event Grid</li>
</ul>
</li>
</ul>
<p>次にPubSubを理解する上で以下の重要な単語を解説していきます。</p>
<p>PubSub概念を理解をする上では少なくとも以下は必須の用語となるので各用語の解説後、図解でPubSubの実際の動きやユースケースを解説していきます。</p>
<ul>
<li>メッセージ</li>
<li>publisher</li>
<li>subscriber</li>
<li>topic</li>
<li>subscription</li>
<li>確認応答（Ack）</li>
</ul>
<h3 id="2-PubSubを理解する上で重要な単語の解説">2. PubSubを理解する上で重要な単語の解説</h3><ol>
<li><strong>メッセージについて</strong><br>メッセージとは、異なるコンポーネントや、アプリケーションに対して送信するデータのことです。要は非同期的に処理させたいデータをメッセージとして作成します。最終的にpublishする際にはメッセージの形式をバイト配列にする必要があります。(publishに関しては後ほど解説します)</li>
<li><strong>publisherについて</strong><br>publisherとは、メッセージを送信する役割をもつアプリケーションのことを指します。publisherがメッセージを送信することをpublishする、と言います。</li>
<li><strong>subscriberについて</strong><br>subscriberとは、メッセージを受信する役割を持つアプリケーションのことを指します。つまり、publisherからpublish(送信)されたメッセージを受け取り、非同期的に受け取り、それに応じた処理を行うアプリケーションと言えます。</li>
<li><strong>topicについて</strong><br>topicとは、PubSubのコンポーネントでありメッセージの送信元であるpublisherと、メッセージの受信先であるsubscriberを結ぶ中継地点と言えます。つまり、publisherはsubscriberへ直接メッセージをpublishするのではなく、topicにメッセージをpublishしています。topicについては特に重要な概念となります。</li>
<li><strong>subscriptionについて</strong><br>subscriptionとはPubSubのコンポーネントでありtopicからのメッセージの受信先と言え、subscriptionからsubscriberへのメッセージの配信が行われます。また、topicからメッセージを受信するsubscriptionは必ずしも１つである必要はなく、複数のsubscriptionを作成し１つのメッセージに対し、複数のsubscriberにメッセージを一度に配信することで全く違う処理を同時に非同期的に行うことが可能です。</li>
<li><strong>確認応答（Ack）について</strong><br>subscriberがメッセージを正常に受け取ったらsubscriptionに対して正常にメッセージを受信したことを通知します。確認応答を受信すると正常にメッセージが受信されたと見なされ、そのメッセージはtopicから削除されます。また、subscriberがメッセージの処理に失敗した場合、Nack（Negative Acknowledgement）を通知できます。Nackが通知された場合、再度メッセージを配信します。この辺りの詳細な設定もsubscriptionで決めることが可能です。</li>
</ol>
<h3 id="3-実際の処理の流れの解説">3. 実際の処理の流れの解説</h3><img fetchpriority="high" src="/images/2023/20230613a/pubsub_1.png" alt="pubsub" width="667" height="435">

<p>上図がPubSubの基本的な処理の流れになっています。</p>
<p>流れとしては以下のような流れとなります。</p>
<ul>
<li><ol>
<li>publisherがメッセージを作成、topicへpublishする</li>
</ol>
</li>
<li><ol start="2">
<li>publishされたメッセージはMessageStorageへ格納される（MessageStorageについては説明していませんが、要はメッセージの一時保存場所のイメージです）</li>
</ol>
</li>
<li><ol start="3">
<li>topicにpublishされたメッセージはsubscriptionの設定内容に応じてsubscriberへ配信されます。</li>
</ol>
</li>
<li>4~5. subscriberがメッセージを正常に受信したことをsubscriptionへ通知します（Ackされる）</li>
</ul>
<p>また、下図のような1対N・N対1のような使い方もできます。</p>
<p>例えば下図のpublisher Cから複数のsubscriberへメッセージを配信するユースケースは以下のようなシナリオが考えられると思います。</p>
<ul>
<li>ECサイトの注文管理システムの注文通知機能<ol>
<li>Publisher Cが注文データをメッセージとしてpublish</li>
<li>PublishされたメッセージをTopic Cが受信</li>
<li>Topic cがSubscription YCとSubscription ZCへメッセージを配信</li>
<li>Subscriber YとSubscriber Zがメッセージを受信</li>
<li>Subscriber Yはユーザへの注文確定のメール通知を行う・Subscriber Zは管理者ダッシュボードへの注文通知を表示する</li>
</ol>
</li>
</ul>
<p>上記はあくまでPubSubを用いた一例ですが、このように異なるサービスやシステム間での効率的な処理が可能になるのがPubSubの凄さだと思っています。</p>
<img src="/images/2023/20230613a/pubsub_2.png" alt="pubsub_2.png" width="727" height="418" loading="lazy">

<h3 id="4-PubSubを使用したユースケース考えてみた">4. PubSubを使用したユースケース考えてみた</h3><p>用語の解説から実際の処理の流れの解説までできたところで、今度はユースケースを考えてみます。</p>
<p>例えば下図のような証券会社のシステムがあったとします。</p>
<p>このシステムは10年以上前に構築されたもので以下のような課題がありました。</p>
<ul>
<li>課題（1）：各種取引商品データ更新の遅延<ul>
<li>10年前と比較して取引商品が増えたため、更新処理時間が増加していた。</li>
</ul>
</li>
<li>課題（2）：システム依存度の高さ<ul>
<li>現行のシステムではデータプロパイダと直接的に連携していることにより、他のデータプロパイダの使用やシステムのアップグレードが非常に難しくなっていた。</li>
</ul>
</li>
</ul>
<img src="/images/2023/20230613a/pubsub_3.jpg" alt="pubsub_3.jpg" width="1170" height="721" loading="lazy">

<p>下図のようにPubSubを導入することによってこれらの課題を解決できます（あくまで一例です）</p>
<ul>
<li>課題（1）：各種取引商品データ更新の遅延<ul>
<li>現行のシステムでは大量のデータを１つのシステムが処理をしていたが、データをメッセージとして受け取り複数のsubscriberで並列的に処理をさせる（データを表示するsubscriber、データを登録するsubscriberなどで役割を分ける）ことで効率的に処理を行う。</li>
</ul>
</li>
<li>課題（2）：システム依存度の高さ<ul>
<li>PubSubを介することでデータプロパイダと証券会社システム間は疎結合な関係になることで他のデータプロパイダの使用やアップグレードが現行システムより容易になる。</li>
</ul>
</li>
</ul>
<img src="/images/2023/20230613a/pubsub_4.jpg" alt="pubsub_4.jpg" width="1170" height="918" loading="lazy">

<h2 id="5-まとめ">5.まとめ</h2><p>PubSubを理解するうえで必要な用語の解説からユースケースまで説明しました。</p>
<p>今回はPubSubの解説を、主にイベントドリブンなアーキテクチャで例えて解説しましたが、他にもリアルタイム分析や、マイクロサービスアーキテクチャの実現など様々な用途に使用できます。</p>
<p>私は現在のプロジェクトで初めてPubSubを触りましたが、とても感動しました。</p>
<h2 id="6-さいごに">6.さいごに</h2><p>今回はPubSubの基礎的な部分とユースケースの解説をさせていただきました。</p>
<p>Pull型配信やPush型配信、デッドレターキュー（DLQ）など、まだまだ解説できていない箇所がありますが、次回以降の投稿で解説していこうと思います。</p>
]]></content>
    <summary type="html">PubSubについて噛み砕いて説明していきます。今後PubSubを使用した開発をする方の助けになれればと思います。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="GoogleCloud" scheme="https://future-architect.github.io/tags/GoogleCloud/"/>
    <category term="PubSub" scheme="https://future-architect.github.io/tags/PubSub/"/>
    <category term="初心者向け" scheme="https://future-architect.github.io/tags/%E5%88%9D%E5%BF%83%E8%80%85%E5%90%91%E3%81%91/"/>
  </entry>
  <entry>
    <title>AWS Kinesisから呼び出されるLambdaのリカバリー処理について</title>
    <link href="https://future-architect.github.io/articles/20230526a/"/>
    <id>https://future-architect.github.io/articles/20230526a/</id>
    <published>2023-05-25T15:00:00.000Z</published>
    <updated>2023-05-25T15:00:00.000Z</updated>
    <author><name>原木翔</name></author>
    <content type="html"><![CDATA[<h2 id="はじめに">はじめに</h2><p>TIGの原木です。</p>
<p>最近、AWS Kinesis Data StreamとAWS Lambdaを組み合わせたデータストリーミングを扱うシステムで、Lambdaが処理に失敗した場合のリカバリー運用を考える機会がありました。</p>
<p>一般的に、Kinesisのようなメッセージングやイベント駆動型のシステムでは、DLQ(デッドレターキュー)という仕組みを設けます。DLQの目的は、メインアプリケーションが障害やバグにより正常に動かなかった場合、未処理のメッセージやイベントを、メインシステムとは”別口の”キューに隔離、保存することです。これにより、運用者はシステムデータのリカバリーを安全に行うことができます。</p>
<p>本記事では、KinesisとLambdaを組み合わせて使用する際に、DLQとしてDestinationsを使用したフェールセーフ機能を構築した際の知見を共有したいと思います。</p>
<h2 id="3行まとめ">3行まとめ</h2><ul>
<li>LambdaのDestinationsの設定には「非同期呼び出し」と「ストリーム呼び出し」があります</li>
<li>設定したリトライ回数が超過しないとDestinations(Fail)は呼び出されません</li>
<li>「非同期呼び出し」と「ストリーム呼び出し」はFail時に渡されるメッセージの構造が違うため、再処理には注意が必要です</li>
</ul>
<h2 id="システム説明">システム説明</h2><p>アーキテクチャ図をベースにフェールセーフ機能の全体概要について説明します。</p>
<img fetchpriority="high" src="/images/2023/20230526a/Kinesis.drawio.png" alt="Kinesis.drawio.png" width="1200" height="321">

<h3 id="1-2-Kinesisからのデータ連携">1~2. Kinesisからのデータ連携</h3><p>システムで利用するデータは外部システムからKinesisを通じて送られてきます。</p>
<p>ここで着目してほしいのがKinesisは、内部アカウントと外部アカウントの両方に存在することです。本来なら、アカウントの違いなど気にせず、同じ設定を持ちまわしたいのですが、現状Kinesisのクロスアカウントはサポートしておらず、異なるアカウントのKinesisストリームから直接Lambdaに接続できません(2023年4月現在)</p>
<p>この問題を解決するために、外部アカウントには中間にLambda(ポーラー)を配置して、ポーラーが他のアカウントのKinesisストリームからデータを受信し、Lambda(メインのビジネスロジック)に非同期でデータを渡すようにします。つまり、ポーラーは異なるアカウントのKinesisとLambdaを接続する橋渡しの役割を果たします。</p>
<p>内部アカウントでは、そのような仕組みは必要ないため、直接KinesisとLambda(メインのビジネスロジック)を接続しています。</p>
<div class="note-container note-info"><span class="note-icon"></span><div><p>中継用のLambdaを設けて、データの橋渡しをするやり方はAWSの情報センターにある下記の情報を参考にしています。</p>
<p>「クロスアカウントの Kinesis ストリームを使用して、私の Lambda 関数を呼び出す方法を教えてください？」<br>https://repost.aws/ja/knowledge-center/lambda-cross-account-kinesis-stream</p>
<p>本文の警告にあるように、この方法が決してベストというわけではありませんが、本案件では様々な事情を鑑みたうえで採用させていただきました。</p>
<blockquote>
<p>本文の警告:</p>
<p>この設定により、Kinesis Data Streams を使用する利点の多くがなくなります。この手順の完了後は、シャード内でレコードをブロックしたり、順序付けを作成したりすることはできません。アプリケーションがこれらの特徴を使用する必要がない場合にのみ、この回避策を使用することをお勧めします。</p>
</blockquote></div></div>

<h3 id="3-Lambdaで処理が失敗した時にSQSへ処理データを送る">3. Lambdaで処理が失敗した時にSQSへ処理データを送る</h3><p>Kinesisから送られたデータは、Lambda(メインのビジネスロジック)で処理されます。</p>
<p>Lambda(メインのビジネスロジック)で処理に失敗した場合、LambdaのDestinations(Failure)経由でAWS SQSに処理しようとしていたデータが送られます。 <sup id="fnref:3">1</sup></p>
<p>SQSはDLQの役割をし、正常に処理できないデータを受け取ります。</p>
<h3 id="4-失敗した処理データを永続化する">4. 失敗した処理データを永続化する</h3><p>Lambda(運用監視)は、SQSから呼ばれて、Lambda(メイン)で処理に失敗したデータを受け取り、S3に出力します。</p>
<h3 id="5-リカバリー-運用サーバーからデータを再送する">5. リカバリー: 運用サーバーからデータを再送する</h3><p>障害発生の諸々のプロセスを踏んで、状況解消後、S3に出力したデータは運用サーバーから再送されます。</p>
<h2 id="システムの設計で迷ったところ-嵌ったところ">システムの設計で迷ったところ&#x2F;嵌ったところ</h2><h3 id="LambdaからDestinations-SQS-が呼ばれない？">LambdaからDestinations(SQS)が呼ばれない？</h3><p>Lambdaで処理に失敗してもDestinationsが呼ばれないように見えるケースがあります。<br>下記項目が適切に設定できているか確認してください。</p>
<ul>
<li>LambdaのIAM RoleにSQSへの書き込み権限が付与されているか？</li>
<li>Lambdaの呼び出し元に応じて「非同期呼び出し」と「ストリーム呼び出し」を適切に設定できているか？</li>
<li>Lambdaの「リトライ」回数に上限が設定されているか？</li>
</ul>
<p>これらの設定をしていないとDestinationsが期待通りに動作しません。<br>ここでは一番最後のリトライ回数について詳細を見ていきます。</p>
<h4 id="Lambdaのリトライ回数を明示的に設定しなかったら？">Lambdaのリトライ回数を明示的に設定しなかったら？</h4><p>LambdaのDestinationsはリトライ回数を超過しないと呼ばれません。</p>
<p>AWS側の仕様で、「非同期呼び出し」は上限が2回までと決まっているのですが「ストリーム呼び出し」には上限がありません。そのため、リトライ回数のパラメータを明示的に設定しなかった場合の挙動も違います。</p>
<p>ここで、AWSのリソースをTerraformから操作するためのプラグインであるTerraform Provider for AWSのコードを見てみましょう。</p>
<p>「非同期呼び出し」では次の通りになっています。</p>
<figure class="highlight go"><table><tr><td class="code"><pre><span class="line"><span class="string">&quot;maximum_retry_attempts&quot;</span>: &#123;</span><br><span class="line">	Type:         schema.TypeInt,</span><br><span class="line">	Optional:     <span class="literal">true</span>,</span><br><span class="line">	Default:      <span class="number">2</span>,</span><br><span class="line">	ValidateFunc: validation.IntBetween(<span class="number">0</span>, <span class="number">2</span>),</span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure>

<p>https://github.com/hashicorp/terraform-provider-aws/blob/0a77465627efb9003f87978f901d1a4004a2fc09/internal/service/lambda/function_event_invoke_config.go#L84</p>
<p>リトライ回数は0~2回が選択できること、デフォルトが2回であることが読み取れます。</p>
<p>一方で、「ストリーム呼び出し」では次の通りになっています。</p>
<figure class="highlight go"><table><tr><td class="code"><pre><span class="line"><span class="string">&quot;maximum_retry_attempts&quot;</span>: &#123;</span><br><span class="line">    Type:         schema.TypeInt,</span><br><span class="line">	Optional:     <span class="literal">true</span>,</span><br><span class="line">	Computed:     <span class="literal">true</span>,</span><br><span class="line">	ValidateFunc: validation.IntBetween(<span class="number">-1</span>, <span class="number">10_000</span>),</span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure>

<p>https://github.com/hashicorp/terraform-provider-aws/blob/0a77465627efb9003f87978f901d1a4004a2fc09/internal/service/lambda/event_source_mapping.go#L199</p>
<p>デフォルトの設定が見当たりませんね。明文化されているわけではありませんが、この裏でリトライ回数は「-1」回&#x3D;無限回が設定されます。したがって、デフォルト設定ではストリーム呼び出しをする側(AWS Kinesis等)のデータ保持期間が切れるまでリトライし続けるため、その間、Destinationsが呼ばれることはありません。</p>
<div class="note-container note-info"><span class="note-icon"></span><div><p>この辺を意識せずに、非同期呼び出しのDestinationsとして作りこんでいた箇所をそのままストリーム呼び出し用に持って行った結果、自分はドはまりすることになりました。</p></div></div>

<h3 id="同じKinesisなのにデータが異なる？">同じKinesisなのにデータが異なる？</h3><p>非同期呼び出しとストリーム呼び出しでは、処理に失敗してDestinationsを介して渡されるエラーメッセージの形式は異なります。</p>
<p>実際にビジネスロジックでFailして、SQSに渡されたメッセージデータを横取りして確認してみましょう。</p>
<figure class="highlight json"><table><tr><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;Messages&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">        <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;MessageId&quot;</span><span class="punctuation">:</span> <span class="string">&quot;0fb6346c-7654-40e2-af70-5d6b85fca0ad&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;ReceiptHandle&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">null</span></span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;MD5OfBody&quot;</span><span class="punctuation">:</span> <span class="string">&quot;263d2add8083eb244875245998bb53d9&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;Body&quot;</span><span class="punctuation">:</span> <span class="string">&quot;&#123;\&quot;version\&quot;: \&quot;1.0\&quot;, \&quot;timestamp\&quot;: ...(ここに違いが出る)&quot;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">]</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>

<p>SQSのフォーマット自体は非同期呼び出しとストリーム呼び出しで違いはありません。両者が異なるのはこのメッセージデータのうち、 <code>Body</code> の内容です。 <code>Body</code> には文字列として入っているので、元のJSONデータとして扱うには復元処理が必要です。</p>
<figure class="highlight py"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 復元処理と書くと大仰ですが、Pythonで書いたら実際はこんな感じです。</span></span><br><span class="line">sqs_message = event[<span class="string">&quot;body&quot;</span>]</span><br><span class="line">sqs_message_dict = json.loads(sqs_message)</span><br></pre></td></tr></table></figure>

<p>こうやって取り出したメッセージデータの違いについてみていきましょう。「非同期呼び出し」では次のようになっています。</p>
<figure class="highlight json"><table><tr><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;version&quot;</span><span class="punctuation">:</span> <span class="string">&quot;1.0&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;timestamp&quot;</span><span class="punctuation">:</span> <span class="string">&quot;タイムスタンプ&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;requestContext&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;requestId&quot;</span><span class="punctuation">:</span> <span class="string">&quot;リクエストID&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;functionArn&quot;</span><span class="punctuation">:</span> <span class="string">&quot;メインロジックLambdaのARN&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;condition&quot;</span><span class="punctuation">:</span> <span class="string">&quot;RetriesExhausted&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;approximateInvokeCount&quot;</span><span class="punctuation">:</span> <span class="number">3</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;requestPayload&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;KinesisRecord&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;approximateArrivalTimestamp&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Kinesisがレコードを受信した時刻&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;data&quot;</span><span class="punctuation">:</span> <span class="string">&quot;処理するはずだったデータの内容&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;partitionKey&quot;</span><span class="punctuation">:</span> <span class="string">&quot;パーティションキー&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;sequenceNumber&quot;</span><span class="punctuation">:</span> <span class="string">&quot;シーケンス番号&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;kinesisSchemaVersion&quot;</span><span class="punctuation">:</span> <span class="string">&quot;1.0&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;responseContext&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;statusCode&quot;</span><span class="punctuation">:</span> <span class="number">200</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;executedVersion&quot;</span><span class="punctuation">:</span> <span class="string">&quot;$LATEST&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;functionError&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Unhandled&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;responsePayload&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;errorMessage&quot;</span><span class="punctuation">:</span> <span class="string">&quot;エラーメッセージ&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;errorType&quot;</span><span class="punctuation">:</span> <span class="string">&quot;wrapError&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>

<p>ここで、着目したいのが <code>requestPayload</code> 配下です。この要素には、本来ビジネスロジックで処理する予定だったデータが渡されます。</p>
<p>したがって、このデータを元にリカバリーしたいと思った場合、<code>requestPayload.KinesisRecord</code> を取り出してAWS Lambdaに渡せば、再実行できます。</p>
<p>しかし、「ストリーム呼び出し」では同じ手段ではうまくいきません。Bodyの内容を同様に見てみましょう。</p>
<figure class="highlight json"><table><tr><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;requestContext&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;requestId&quot;</span><span class="punctuation">:</span> <span class="string">&quot;リクエストID&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;functionArn&quot;</span><span class="punctuation">:</span> <span class="string">&quot;メインロジックLambdaのARN&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;condition&quot;</span><span class="punctuation">:</span> <span class="string">&quot;RetryAttemptsExhausted&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;approximateInvokeCount&quot;</span><span class="punctuation">:</span> <span class="number">3</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;responseContext&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;statusCode&quot;</span><span class="punctuation">:</span> <span class="number">200</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;executedVersion&quot;</span><span class="punctuation">:</span> <span class="string">&quot;$LATEST&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;functionError&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Unhandled&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;version&quot;</span><span class="punctuation">:</span> <span class="string">&quot;1.0&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;timestamp&quot;</span><span class="punctuation">:</span> <span class="string">&quot;タイムスタンプ&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;KinesisBatchInfo&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;shardId&quot;</span><span class="punctuation">:</span> <span class="string">&quot;shardId-000000000000&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;startSequenceNumber&quot;</span><span class="punctuation">:</span> <span class="string">&quot;シーケンス番号の開始&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;endSequenceNumber&quot;</span><span class="punctuation">:</span> <span class="string">&quot;シーケンス番号の終了&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;approximateArrivalOfFirstRecord&quot;</span><span class="punctuation">:</span> <span class="string">&quot;レコードのざっくり開始受信日時&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;approximateArrivalOfLastRecord&quot;</span><span class="punctuation">:</span> <span class="string">&quot;レコードのざっくり終了受信日時&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;batchSize&quot;</span><span class="punctuation">:</span> <span class="string">&quot;バッチサイズ&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;streamArn&quot;</span><span class="punctuation">:</span> <span class="string">&quot;kinesisのARN&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>

<p>先ほど要素として存在した <code>requestPayload</code> (と <code>responsePayload</code>) が消えて<br>代わりに <code>KinesisBatchInfo</code> が追加されていることがわかります。</p>
<p><code>requestPayload</code> と <code>KinesisBatchInfo</code> の違いは何でしょうか？</p>
<p><code>requestPayload</code> には、AWS Lambdaを実行時に渡されるデータがそのまま入っています。したがって、<code>requestPayload</code> の下のデータをAWS Lambdaに再送すればそのまま再実行できます。</p>
<p>しかし、 <code>KinesisBatchInfo</code> には Kinesisから渡されたデータは入っていません。代わりに、Kinesis内のデータ&#x3D;レコードを示すいわゆる “ポインタ” にあたる情報が入っており、この情報を元に、Kinesisからレコードを見つけて再送する必要があります。</p>
<p>この辺の手順は AWSの公式ドキュメント「AWS CLI を使用した基本的な Kinesis Data Stream オペレーションの実行-ステップ 3: レコードを取得する」に詳しい記載があります。</p>
<p>リカバリー処理の実装は、両者の違いを踏まえて行う必要があります。</p>
<h2 id="まとめ">まとめ</h2><p>以上、AWS Kinesisから呼び出されるLambdaのリカバリー処理についての解説でした。最後に、比較表を掲載します。</p>
<div class="scroll"><table>
<thead>
<tr>
<th>No</th>
<th>AWS Lambda(メインロジック)の呼び出し方</th>
<th>自システムでの利用シーン</th>
<th>リトライ処理(デフォルト)</th>
<th>リカバリー処理を実装するために必要な要素</th>
<th>リカバリー処理の実装方法</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>非同期呼び出し</td>
<td>異なるAWSアカウントからのKinesisデータ連携</td>
<td>2回</td>
<td>requestPayload</td>
<td>Lambda(メインロジック)を呼び出して requestPayloadを渡す</td>
</tr>
<tr>
<td>2</td>
<td>ストリーム呼び出し</td>
<td>同じAWSアカウントからのKinesisデータ連携</td>
<td>無限</td>
<td>KinesisBatchInfo</td>
<td>KinesisからKinesisBatchInfoを元にシャードイテレーターを通じてレコードを取得し、 再びKinesisに送信する</td>
</tr>
</tbody></table></div>
<div class="note-container note-info"><span class="note-icon"></span><div><p>運用側では当然両者のデータの違いを意識したくなかったのでリカバリー処理のためにツールを実装しました。二種類の異なるコードを書きつつ、両者とも元はKinesisのデータなんだけどなっていう、もったいない？ 気持ちがありつつも、違いについて勉強になりました。</p>
<p>Kinesisのクロスアカウントサポート来てほしいです…</p></div></div>

<div id="footnotes"><hr><div id="footnotelist"><ol style="list-style:none; padding-left: 0;"><li id="fn:3"><span style="vertical-align: top; padding-right: 10px;">1.</span><span style="vertical-align: top;">私信なのでコメントで補足します: そもそも、Lambdaを非同期で呼び出して処理に失敗した場合、データの送信先として「DLQ」と「Destinations」を選ぶことができます。どちらを使ってよいかAWSを最近使いだしたユーザーには判断が難しいところだと思います。両者を比較しても「DLQでできることは全部Destinationsでできるよ」という推しの弱い結論しか出てこないのではないでしょうか。そもそも両者が似たような機能なのは必然なのかもしれません。時系列でみてみると、DLQが2016年、Destinationsが2019年と、Destinationsが後発組です。そのためか、DLQの既存ユーザーのためにDLQとDestinationsが両方利用できるように残してるのでは？ (だから、似た機能なのか)と読み取れる記述がテックブログにあります。「Destinations and DLQs can be used together and at the same time although Destinations should be considered a more preferred solution. 」(DestinationsとDLQは同時に使用できますが、Destinationsの方がより好ましいソリューションです) これを見る限りでは「AWS公式の資料でもういっそ、DLQの後継機能がDestinationsだから、Destinationsを使いましょう」ってはっきり言いきっちゃってほしい、とぼやきたいところです。あえて機能面に踏み込むなら、Destinations経由で渡されるメッセージにはAWS LambdaのARNが入っているのでコールバックが楽だし、失敗時だけでなく成功時でもハンドリングやメトリクスを取得したい機会が来るから機能拡張の容易な「Destinations」を選択しようというのが今できる説明かなと存じます。</span> ↩</li></ol></div></div>]]></content>
    <summary type="html">AWS Kinesis Data StreamとAWS Lambdaを組み合わせたデータストリーミングを扱うシステムで、Lambdaが処理に失敗した場合のリカバリー運用を考える機会がありました。一般的に、Kinesisのようなメッセージングやイベント駆動型のシステムでは、DLQという仕組みを設けます。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="AWS" scheme="https://future-architect.github.io/tags/AWS/"/>
    <category term="Kinesis" scheme="https://future-architect.github.io/tags/Kinesis/"/>
    <category term="Lambda" scheme="https://future-architect.github.io/tags/Lambda/"/>
    <category term="リトライ" scheme="https://future-architect.github.io/tags/%E3%83%AA%E3%83%88%E3%83%A9%E3%82%A4/"/>
  </entry>
  <entry>
    <title>Amazon OpenSearch Serverless を触ってみた</title>
    <link href="https://future-architect.github.io/articles/20230525a/"/>
    <id>https://future-architect.github.io/articles/20230525a/</id>
    <published>2023-05-24T15:00:00.000Z</published>
    <updated>2023-05-24T15:00:00.000Z</updated>
    <author><name>齊藤英比古</name></author>
    <content type="html"><![CDATA[<p>春の入門連載2023、17日ぶり23回目の寄稿、23日目を担当します齊藤です。よろしくお願いします。<br>運良く2個目の記事をアップできることになりました！ (やったね)</p>
<p>業務でAmazon OpenSearch Service (Serviceのほう) を触る機会があり、興味があったのでプレビューで公開されていたServerless版でいろいろ試しました。</p>
<p>触っていた内容を入門向けにまとめて、ぜひ参考にしつつ入門していただければです。</p>
<p>Black Belt の資料が大変参考になりました。こちらを適宜引用しています。<br>AWS BLACK BELT ONLINE SEMINAR Amazon OpenSearch Serverless<br>引用：[AWS Black Belt Online Seminar 2023&#x2F;01] Amazon OpenSearch Serverless</p>
<p><strong>注意！</strong><br>Serverless版は、無料利用枠がないため、入門のために少し触るだけでも費用がかかります。</p>
<p>参考までに自分の場合は、5,6回コレクションを作成したり消したりAPI叩いたりで、800円くらいの請求でした。無料枠で OpenSearch を試したい場合は、Service版を使ってください。</p>
<p>いくらかかかってもいいけどとりあえず触って感触掴みたい！ みたいな方はServerless版をどうぞ。</p>
<h2 id="Amazon-OpenSearch-Serverless">Amazon OpenSearch Serverless</h2><p>プレビュー版から一般提供開始にかわりました。</p>
<p>https://aws.amazon.com/jp/about-aws/whats-new/2023/01/amazon-opensearch-serverless-available/</p>
<h2 id="そもそも-OpenSearch-とは？">そもそも OpenSearch とは？</h2><blockquote>
<p>OpenSearch は、リアルタイムのアプリケーションモニタリング、ログ分析、ウェブサイト検索などの幅広いユースケースにご利用いただける分散型、コミュニティ主導型、Apache 2.0 ライセンス、100% オープンソースの検索および分析スイートです。</p>
<p>引用：[AWS公式] OpenSearch とは https://aws.amazon.com/jp/what-is/opensearch/</p>
</blockquote>
<p>検索・分析ができる、いわゆる全文検索エンジンと呼ばれるものになります。</p>
<p>次に出てくる、全文検索とは何か？</p>
<blockquote>
<p>全文検索（ぜんぶんけんさく、英: Full text search）とは、コンピュータにおいて、複数の文書（ファイル）から特定の文字列を検索すること。「ファイル名検索」や「単一ファイル内の文字列検索」と異なり、「複数文書にまたがって、文書に含まれる全文を対象とした検索」という意味で使用される。</p>
<p>引用：[ウィキペディア (Wikipedia): フリー百科事典] 全文検索（2023年5月24日取得，https://ja.wikipedia.org/w/index.php?title=全文検索&amp;oldid=94342252）</p>
</blockquote>
<p>OpenSearch では、引用元のページにも出てくる「転置インデックス」を使っています。<br>詳しく知りたい方は、以下を参照ください。<br>[Amazon OpenSearch Service Intro Workshop] 逐次検索と転置インデックス</p>
<p>とりあえず触りたい人向けに個人的にまとめると、全文検索というSQLのLike句よりめっちゃ速く文字列を検索できるというもの。その速さを活かして、例えば、アプリケーションが出す大量のログからエラーを検知させたり、ユーザーの動向を調べたり、といった分析とその結果のレポート出力などなど周りの機能も提供しているという印象。</p>
<p>補足<br>他にも有名な全文検索エンジンで「Elasticsearch」があります。<br>元々は、「Amazon Elasticsearch Service」として「オープンソースのElasticsearch」がAWS上でマネージドサービスとして提供されていましたが、バージョン7.10以降において別のライセンス体系となりAWS上でこれまで通り利用できなくなることから「オープンソースのElasticsearch」から派生し「OpenSearch」が作られました。この成り立ちにより「Elasticsearch」と「OpenSearch」は類似点が多くあります。実際にバージョン7.10までは互換性がありAWS側では当該バージョンまではサポートする旨が記載されています。しかし、それ以降のバージョンについては、互換性が保証されておらず、別のソフトウェアとして位置付けられているため、互換性や機能有無についてはご注意ください。<br>(上記にはライセンス変更や名称変更には背景があるのですが……何があったのか気になる方は、このあたりの記事から色々見てみてください……)</p>
<p>https://www.elastic.co/jp/blog/elastic-and-amazon-reach-agreement-on-trademark-infringement-lawsuit</p>
<h2 id="Amazon-OpenSearch-Serverless-概要">Amazon OpenSearch Serverless 概要</h2><ul>
<li>Amazon OpenSearch Service のサーバーレス版</li>
<li>クライアントは Amazon OpenSearch Service と同様の方法で操作可能</li>
<li>OpenSearch のクラスタのスケーリングなどの管理が不要<br>データの投入や検索の負荷増大に合わせて勝手にスケールアウトしてくれるらしい</li>
<li>少しの手順、数分で構築が可能 (入門におすすめの理由)</li>
<li>Hot node、UltraWarm node とノードに種類があり、時系列コレクションの場合に直近24時間のデータはHot nodeにいれ、それ以降はUltraWarm nodeにいれることでノードの増大を防ぐ (Serverless版のいいところと思われ)</li>
</ul>
<img fetchpriority="high" src="/images/2023/20230525a/Black_Belt_Amazon_OpenSearch_Serverless_27スライド.png" alt="Black_Belt_Amazon_OpenSearch_Serverless_27スライド" width="1200" height="679">
[引用元 2023/01 [AWS Black Belt Online Seminar] Amazon OpenSearch Serverless 27スライド目](https://pages.awscloud.com/rs/112-TZM-766/images/AWS-Black-Belt_2023_AmazonOpenSearchServerless_0131_v1.pdf)

<h3 id="公式ページはこちら">公式ページはこちら</h3><ul>
<li>https://aws.amazon.com/jp/opensearch-service/features/serverless/</li>
</ul>
<p>公式ページでは、以下の情報がまとまっています。</p>
<h4 id="リソース">リソース</h4><ul>
<li>ポッドキャスト<ul>
<li>Amazon OpenSearch Serverless の紹介</li>
</ul>
</li>
<li>ワークショップ<ul>
<li>Amazon OpenSearch Serverless を実際に体験する</li>
</ul>
</li>
<li>ブログ<ul>
<li>Amazon OpenSearch Serverless の簡単な方法によるログ分析</li>
</ul>
</li>
<li>動画<ul>
<li>re:Invent 2022: Provision and scale OpenSearch resources with serverless</li>
<li>デモ: Searching with Amazon OpenSearch Serverless</li>
<li>デモ: Log analytics with Amazon OpenSearch Service</li>
</ul>
</li>
</ul>
<h2 id="お試し">お試し</h2><ol>
<li><p><strong>Amazon OpenSearch Serverless の TOP</strong></p>
<ul>
<li>Amazon OpenSearch Service のトップにサーバーレスのメニューが追加されておりそこからサーバーレス版にアクセスができる<br>※画像のオレンジ枠が該当箇所<img src="/images/2023/20230525a/サーバーレス版へのアクセス.png" alt="サーバーレス版へのアクセス" width="1200" height="599" loading="lazy"></li>
</ul>
</li>
<li><p><strong>インデックスを格納するのはコレクション</strong></p>
<ul>
<li>インデックスというのは、RDBで言うところのテーブルのようなもの。OpenSearch Service では、EC2インスタンスに対しインデックスを格納する</li>
<li>OpenSearch Serverlessでは、コレクションという単位で作成しコレクションに対しインデックスを作成する<img src="/images/2023/20230525a/サーバーレスダッシュボード.png" alt="サーバーレスダッシュボード" width="1200" height="532" loading="lazy"></li>
</ul>
</li>
<li><p><strong>コレクションを作成してみる</strong></p>
<ul>
<li>コレクションの名前、説明、コレクションタイプの設定ができる。コレクションタイプは、時系列と検索の2種類から選べる。<br>名前と説明はいい感じのものを入れて、コレクションタイプは検索を選びましょう。<br>(時系列を選ぶと、前述の通り直近24時間分のデータしか検索対象とならない)<img src="/images/2023/20230525a/Add_new_collection.png" alt="Add_new_collection" width="921" height="637" loading="lazy"></li>
<li>暗号化<br>初学者の方は、「AWS 所有キーを使用する」でAWSにおまかせしましょう。自前で用意したい方は、もう1つの方で。<img src="/images/2023/20230525a/encryption.png" alt="encryption" width="905" height="410" loading="lazy"></li>
<li>ネットワークアクセス<br>今回はアクセスタイプにVPCは使わずにパブリックを利用します。 <del>VPCの説明までするとめんどくさいので</del> OpenSearch に絞って学べるようパブリックです。後ほどアクセスポリシー内でIAMユーザーでのアクセスとするので、誰でも触れる！ というわけではないので安心してください。<br>※説明でAPIのエンドポイントとダッシュボードのエンドポイントで異なるネットワーク設定をできるような記述があるが、注釈の方で同じ設定にするよう記載がある<img src="/images/2023/20230525a/network_access.png" alt="network_access" width="909" height="521" loading="lazy"></li>
<li>データのアクセスポリシー<br>データへのアクセス権のルールを作成できます。<br>わかりやすくビジュアルエディタで作成していきます。<img src="/images/2023/20230525a/Configure_data_access_1.png" alt="Configure_data_access_1" width="945" height="367" loading="lazy"></li>
<li>テンプレートやインデックス、ドキュメントに対し権限を付与できます<br>「エイリアスとテンプレートの許可」「インデックスの許可」どちらもすべてチェックします。<img src="/images/2023/20230525a/Configure_data_access_2.png" alt="Configure_data_access_2" width="937" height="669" loading="lazy"></li>
<li>プリンシパルにはIAMとSAMLを選択できる。<img src="/images/2023/20230525a/Configure_data_access_2-1.png" alt="Configure_data_access_2-1" width="938" height="203" loading="lazy"></li>
<li>「IAM ユーザーとロール」を選択するとダイアログが開かれます<img src="/images/2023/20230525a/image.png" alt="image.png" width="820" height="253" loading="lazy"></li>
<li>「ユーザー」を選択すると……<img src="/images/2023/20230525a/image_2.png" alt="image.png" width="819" height="253" loading="lazy"></li>
<li>IAMユーザーの一覧が表示されるので、そこから選んでください<br><img src="/images/2023/20230525a/image_3.png" alt="image.png" width="823" height="288" loading="lazy"><br><br>ビジュアルエディタの場合、最後にアクセス権のルールに名前をつける模様。あとから名前を変えたり、削除したりできるので「新しいデータアクセスポリシーとして作成する」を選択し、いい感じのアクセスポリシー名をつけてください。<img src="/images/2023/20230525a/Configure_data_access_3.png" alt="Configure_data_access_3" width="940" height="651" loading="lazy">
最後に確認画面が出るので、「送信」ボタンを押して続行！数分でステータスがアクティブになり、あちこちにダッシュボードへのリンクが表示されました。</li>
</ul>
</li>
<li><p><strong>作成したコレクションのOpenSearchダッシュボードにアクセスする</strong></p>
<ul>
<li>ダッシュボードにアクセス<br>オレンジ枠の各所をクリックしましたが、画面が表示されず……<br>青枠のURLをコピーして「https:&#x2F;&#x2F;xxxxxxxxxxxxxxxxxxxx.ap-northeast-1.aoss.amazonaws.com&#x2F;_dashboards」とURLの末尾に「&#x2F;_dashboards」をつけることでアクセスできました。<img src="/images/2023/20230525a/image_4.png" alt="image.png" width="1200" height="486" loading="lazy">
こんな感じでOpenSearchダッシュボードが表示されます。
(以前はログイン画面が出ていたのですが、AWSにログインしていると自動でログインされました。便利)
<img src="/images/2023/20230525a/image_5.png" alt="image.png" width="1200" height="500" loading="lazy"><br></li>
</ul>
</li>
<li><p><strong>Dev Tools から OpenSearch API を実行する</strong></p>
<ul>
<li>DevToolsからAPI実行<br>先程のOpenSearchダッシュボードの画面にて、右上の「Dev tools」のリンクをクリックします。<br><img src="/images/2023/20230525a/image_6.png" alt="image.png" width="1200" height="382" loading="lazy"><br><br>DevToolsの画面が開くので好きにAPIを実行しちゃってください。<br><img src="/images/2023/20230525a/image_7.png" alt="image.png" width="1200" height="275" loading="lazy"><br></li>
<li>試しにデベロッパーガイドのチュートリアルの「ステップ3: データをアップロードして検索する」にならってインデックスを作成する<br>以下を入力し、列の右側に再生ボタンのようなアイコンが出るのでクリック</li>
</ul>
<figure class="highlight json"><table><tr><td class="code"><pre><span class="line">PUT movies-index/_doc/<span class="number">1</span></span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;title&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Shawshank Redemption&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;genre&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Drama&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;year&quot;</span><span class="punctuation">:</span> <span class="number">1994</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>

<p>作成できた旨のメッセージが出ます。<br><img src="/images/2023/20230525a/image_8.png" alt="image.png" width="1200" height="283" loading="lazy"></p>
<ul>
<li><code>GET /movies-index/_doc/1</code> を入力、実行してデータが登録できることを確認<img src="/images/2023/20230525a/image_9.png" alt="image.png" width="1200" height="309" loading="lazy">
いい感じですね。</li>
</ul>
</li>
<li><p><strong>あとかたづけ</strong></p>
<ul>
<li>作ったコレクションの削除<br>削除は簡単で、AWS コンソールの画面に戻りトップにある削除ボタンから押し確認ダイアログで削除すれば完了！<br><font color="red">アカウントとパスワードで制御されておりアクセスできないとは言え、インターネット上に公開状態のままなのは良くないため、不要であれば必ず消しましょう。</font><img src="/images/2023/20230525a/image_10.png" alt="image.png" width="1200" height="138" loading="lazy"></li>
</ul>
</li>
</ol>
<h2 id="まとめ">まとめ</h2><p>個人的に、ぱっとOpenSearchが使えるので入門で使うにはちょうどいいのでは？ と思っており、まとめられて非常に満足です。</p>
<p>サービス自体としては、OpenSearchダッシュボードがそのまま使えたり、VPC経由ではService版と同様にコンソールアクセスが可能とのことで、移行はスムーズに行えそう。</p>
<p>中でも勝手にスケールアウトしてくれるのは場合により大変楽になるのではと期待しています。例えば、これまでEBSボリュームを度々拡張しなければいけないような運用をしていた場合にもろもろの作業が減るのは幸せですね(本番環境触るの怖い)</p>
]]></content>
    <summary type="html">Amazon OpenSearch Service を触る機会があり、興味があったのでプレビューで公開されていたServerless版でいろいろ試していました</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="AWS" scheme="https://future-architect.github.io/tags/AWS/"/>
    <category term="OpenSearch" scheme="https://future-architect.github.io/tags/OpenSearch/"/>
    <category term="入門" scheme="https://future-architect.github.io/tags/%E5%85%A5%E9%96%80/"/>
    <category term="全文検索" scheme="https://future-architect.github.io/tags/%E5%85%A8%E6%96%87%E6%A4%9C%E7%B4%A2/"/>
  </entry>
  <entry>
    <title>AWS Application Composerを使ってみた！</title>
    <link href="https://future-architect.github.io/articles/20230509a/"/>
    <id>https://future-architect.github.io/articles/20230509a/</id>
    <published>2023-05-08T15:00:00.000Z</published>
    <updated>2023-05-08T15:00:00.000Z</updated>
    <author><name>佐藤更星</name></author>
    <content type="html"><![CDATA[<h2 id="あいさつ">あいさつ</h2><p>こんにちは。金融グループ所属の佐藤です。<br>春の入門祭りの13日目の記事となります。</p>
<p>2023&#x2F;03&#x2F;07から一般提供が開始された新サービス「AWS Application Composer」を使ってみて、どんな人向けか、強み・弱みは何かというところを見ていきます。</p>
<h2 id="AWS-Application-Composerとは？">AWS Application Composerとは？</h2><p>以下、公式の概要文です（引用元: Application Composer | ホーム）</p>
<blockquote>
<p>AWS Application Composer は、サーバーレスアプリケーションのアーキテクチャ設定、構築の合理化と高速化を支援します。<br>シンプルなドラッグ&amp;ドロップのワークフローを使用して、アプリケーションのデプロイに必要な構成が自動的に生成されます。<br>Infrastructure as Code は、AWS CloudFormation と AWS サーバーレスアプリケーションモデルをベースにしています。</p>
</blockquote>
<p>ざっくりまとめると、</p>
<ul>
<li>AWSサービスを用いた <strong>アーキテクチャの構築を支援</strong> するよ</li>
<li><strong>ドラッグ&amp;ドロップ</strong> を使って直感的に操作ができるよ</li>
<li>裏側ではCFnとSAMを使ってるから <strong>テンプレートを共有</strong> できるよ</li>
</ul>
<p>と書いていて、特に2つ目のドラッグ&amp;ドロップができるよ！ というのがキャッチコピーとなっています。</p>
<p>具体的には以下の画像のように、あるサービスから別のサービスを呼びます、というのをより視覚的に、直感的に表現できます。</p>
<img fetchpriority="high" src="/images/2023/20230509a/スクリーンショット_2023-05-07_23.07.19.png" alt="" width="1200" height="453">

<p>※ドラッグ&amp;ドロップでサービスを配置して、サービス同士を線で繋いでいくイメージ</p>
<h2 id="サービスの特徴">サービスの特徴</h2><h3 id="コストについて">コストについて</h3><p>以下、公式のQ＆Aです。(引用元：FAQ)</p>
<blockquote>
<p>Q: AWS Application Composer にはどの程度のコストがかかりますか?<br>AWS Application Composer は追加料金なしで使用できます。<br>手動で作成した場合と同じ方法で、AWS Application Composer を使用して作成された AWS リソース (S3 バケットや Lambda 関数など) の料金をお支払いいただきます。<br>実際に使用した分の料金のみをお支払いいただきます。<br>最低料金や前払いの義務は発生しません。</p>
</blockquote>
<p>ということで、Application Composerを使ったからと言って<strong>追加の料金は掛からない</strong>とのことでした。</p>
<h3 id="対応しているサービス">対応しているサービス</h3><p>現時点でGUI上で確認できるサービスは以下です。</p>
<img src="/images/2023/20230509a/スクリーンショット_2023-05-07_23.37.44.png" alt="" width="1200" height="651" loading="lazy">

<p>※API gateway &#x2F; Cognito UserPool &#x2F; Cognito UserPoolClient &#x2F; DynamoDB Table &#x2F; EventBridge Event rule &#x2F; EventBridge Schedule &#x2F; Kinesis Stream &#x2F; Lambda Function &#x2F; Lambda Layer &#x2F; S3 Bucket &#x2F; SNS Topic &#x2F; SQS Queue &#x2F; Step Functions State machine</p>
<p>ということで基本的なサービスは揃っているため、<strong>シンプルな構成では困らなさそう</strong>という印象でした。<br>一方、ここにないサービスを使いたい場合はこれだけで完結させることは出来ないため、Application Composerを使うか検討している人は要チェックです。</p>
<h4 id="使えるリージョン">使えるリージョン</h4><p>現在利用できるリージョンは以下。</p>
<ul>
<li>米国東部 (オハイオ)</li>
<li>米国東部 (バージニア北部)</li>
<li>米国西部 (オレゴン)</li>
<li>アジアパシフィック (シンガポール)</li>
<li>アジアパシフィック (シドニー)</li>
<li>アジアパシフィック (東京)</li>
<li>欧州 (フランクフルト)</li>
<li>欧州 (アイルランド)</li>
<li>欧州 (ストックホルム)</li>
</ul>
<p>ということで、東京リージョンやコストの安い米国各地域のリージョンが入っているので、リソースの配置場所に<strong>特殊な要件がない場合は特に困らなさそう</strong>と思いました。</p>
<h2 id="どんな人向け？">どんな人向け？</h2><p>ここまでをまとめると、</p>
<ul>
<li>直感的に操作できる</li>
<li>追加コストはなし</li>
<li>主要サービスは使える</li>
<li>主要地域で使える</li>
</ul>
<p>という特徴がApplication Composerにはあると分かったため、個人的に…</p>
<ul>
<li>シンプルな構成のサービスを爆速で作りたい人</li>
<li>AWSインフラの構築練習をしてみたい人</li>
</ul>
<p>あたりにオススメなのかなと思いました。<br>良くも悪くも想定された構成であれば<strong>非常に楽に</strong>インフラ構築ができるため、前者ではスピード感、後者では手軽さに繋がると思い抜擢してみました。</p>
<h2 id="実際に使ってみた">実際に使ってみた</h2><p>…と、長々特徴について語ってしまいましたが、ここから実際に触ってみて使い勝手や感想を述べてみようかと思います。</p>
<h3 id="やりたい構成">やりたい構成</h3><p>以下のようなSPAを使ったwebアプリを想定して作ってみようと思います。<br><img src="/images/2023/20230509a/スクリーンショット_2023-05-09_1.02.00.png" alt="スクリーンショット_2023-05-09_1.02.00.png" width="520" height="431" loading="lazy"></p>
<h3 id="やってみた">やってみた</h3><ol>
<li><p>まずはAWSコンソールの検索窓で<code>Application Composer</code>と検索</p>
<img src="/images/2023/20230509a/スクリーンショット_2023-05-09_1.48.43.png" alt="スクリーンショット_2023-05-09_1.48.43.png" width="1200" height="611" loading="lazy">
</li>
<li><p>Application Composerのホーム画面が開けました</p>
<img src="/images/2023/20230509a/スクリーンショット_2023-05-08_0.33.05.png" alt="スクリーンショット_2023-05-08_0.33.05.png" width="1200" height="615" loading="lazy">
</li>
<li><p><code>プロジェクトの作成</code>を押下して、もろもろの設定をして空のプロジェクトを<code>Create</code>してみます</p>
<img src="/images/2023/20230509a/スクリーンショット_2023-05-08_0.32.47.png" alt="スクリーンショット_2023-05-08_0.32.47.png" width="1200" height="615" loading="lazy">
</li>
<li><p>編集画面っぽいのが開けました</p>
<img src="/images/2023/20230509a/スクリーンショット_2023-05-09_1.03.16.png" alt="スクリーンショット_2023-05-09_1.03.16.png" width="1200" height="611" loading="lazy">
</li>
<li><p><code>やりたい構成</code>を見つつ、左のメニューからリソースを雑にドラッグ&amp;ドロップしましょう</p>
<img src="/images/2023/20230509a/スクリーンショット_2023-05-09_1.18.55.png" alt="スクリーンショット_2023-05-09_1.18.55.png" width="1200" height="611" loading="lazy">
</li>
<li><p>論理IDを設定してよりそれっぽくします</p>
<img src="/images/2023/20230509a/スクリーンショット_2023-05-09_1.26.39.png" alt="スクリーンショット_2023-05-09_1.26.39.png" width="1200" height="611" loading="lazy">
</li>
<li><p>APIgatewayの中身が寂しかったのでAuthorizer(認可)とエンドポイントの設定を追加します</p>
<img src="/images/2023/20230509a/スクリーンショット_2023-05-09_1.31.59.png" alt="スクリーンショット_2023-05-09_1.31.59.png" width="1200" height="611" loading="lazy">
</li>
<li><p>再度<code>やりたい構成</code>を見て、アクセスを許可したいリソース同士を線で繋ぎます</p>
<img src="/images/2023/20230509a/スクリーンショット_2023-05-09_1.34.49.png" alt="スクリーンショット_2023-05-09_1.34.49.png" width="1200" height="611" loading="lazy">
</li>
<li><p>見た目が汚いので<code>Arrange</code>ボタンを押して整形します</p>
<img src="/images/2023/20230509a/スクリーンショット_2023-05-09_1.36.28.png" alt="スクリーンショット_2023-05-09_1.36.28.png" width="1200" height="611" loading="lazy">
</li>
<li><p>あっという間にこれで完成です。最後にTemplateを押して出来上がったテンプレートを見てみましょう</p>
<img src="/images/2023/20230509a/スクリーンショット_2023-05-09_1.38.04.png" alt="スクリーンショット_2023-05-09_1.38.04.png" width="1200" height="611" loading="lazy"></li>
</ol>
<p>※全文は長いので折りたたみで添付しておきます（見たい人向け）。クリックしてください。</p>
<details><summary>作成したテンプレート</summary><div>

<figure class="highlight yaml"><table><tr><td class="code"><pre><span class="line"><span class="attr">Transform:</span> <span class="string">AWS::Serverless-2016-10-31</span></span><br><span class="line"><span class="attr">Resources:</span></span><br><span class="line">  <span class="attr">uploadFugaFile:</span></span><br><span class="line">    <span class="attr">Type:</span> <span class="string">AWS::Serverless::Function</span></span><br><span class="line">    <span class="attr">Properties:</span></span><br><span class="line">      <span class="attr">Description:</span> <span class="type">!Sub</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">Stack</span> <span class="string">$&#123;AWS::StackName&#125;</span> <span class="string">Function</span> <span class="string">$&#123;ResourceName&#125;</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">ResourceName:</span> <span class="string">uploadFugaFile</span></span><br><span class="line">      <span class="attr">CodeUri:</span> <span class="string">src/Function2</span></span><br><span class="line">      <span class="attr">Handler:</span> <span class="string">index.handler</span></span><br><span class="line">      <span class="attr">Runtime:</span> <span class="string">nodejs18.x</span></span><br><span class="line">      <span class="attr">MemorySize:</span> <span class="number">3008</span></span><br><span class="line">      <span class="attr">Timeout:</span> <span class="number">30</span></span><br><span class="line">      <span class="attr">Tracing:</span> <span class="string">Active</span></span><br><span class="line">      <span class="attr">Events:</span></span><br><span class="line">        <span class="attr">awesomeApiPOSTapifugasupload:</span></span><br><span class="line">          <span class="attr">Type:</span> <span class="string">Api</span></span><br><span class="line">          <span class="attr">Properties:</span></span><br><span class="line">            <span class="attr">Path:</span> <span class="string">/api/fugas/upload</span></span><br><span class="line">            <span class="attr">Method:</span> <span class="string">POST</span></span><br><span class="line">            <span class="attr">RestApiId:</span> <span class="type">!Ref</span> <span class="string">awesomeApi</span></span><br><span class="line">      <span class="attr">Environment:</span></span><br><span class="line">        <span class="attr">Variables:</span></span><br><span class="line">          <span class="attr">BUCKET_NAME:</span> <span class="type">!Ref</span> <span class="string">fugaFileBucket</span></span><br><span class="line">          <span class="attr">BUCKET_ARN:</span> <span class="type">!GetAtt</span> <span class="string">fugaFileBucket.Arn</span></span><br><span class="line">          <span class="attr">TABLE_NAME:</span> <span class="type">!Ref</span> <span class="string">hogeTable</span></span><br><span class="line">          <span class="attr">TABLE_ARN:</span> <span class="type">!GetAtt</span> <span class="string">hogeTable.Arn</span></span><br><span class="line">      <span class="attr">Policies:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">Statement:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="attr">Effect:</span> <span class="string">Allow</span></span><br><span class="line">              <span class="attr">Action:</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObject</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObjectAcl</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObjectLegalHold</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObjectRetention</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObjectTorrent</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObjectVersion</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObjectVersionAcl</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObjectVersionForReplication</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObjectVersionTorrent</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:ListBucket</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:ListBucketMultipartUploads</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:ListBucketVersions</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:ListMultipartUploadParts</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:AbortMultipartUpload</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:DeleteObject</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:DeleteObjectVersion</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:PutObject</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:PutObjectLegalHold</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:PutObjectRetention</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:RestoreObject</span></span><br><span class="line">              <span class="attr">Resource:</span></span><br><span class="line">                <span class="bullet">-</span> <span class="type">!Sub</span> <span class="string">arn:$&#123;AWS::Partition&#125;:s3:::$&#123;fugaFileBucket&#125;</span></span><br><span class="line">                <span class="bullet">-</span> <span class="type">!Sub</span> <span class="string">arn:$&#123;AWS::Partition&#125;:s3:::$&#123;fugaFileBucket&#125;/*</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">DynamoDBCrudPolicy:</span></span><br><span class="line">            <span class="attr">TableName:</span> <span class="type">!Ref</span> <span class="string">hogeTable</span></span><br><span class="line">  <span class="attr">uploadFugaFileLogGroup:</span></span><br><span class="line">    <span class="attr">Type:</span> <span class="string">AWS::Logs::LogGroup</span></span><br><span class="line">    <span class="attr">DeletionPolicy:</span> <span class="string">Retain</span></span><br><span class="line">    <span class="attr">Properties:</span></span><br><span class="line">      <span class="attr">LogGroupName:</span> <span class="type">!Sub</span> <span class="string">/aws/lambda/$&#123;uploadFugaFile&#125;</span></span><br><span class="line">  <span class="attr">getTemplate:</span></span><br><span class="line">    <span class="attr">Type:</span> <span class="string">AWS::Serverless::Function</span></span><br><span class="line">    <span class="attr">Properties:</span></span><br><span class="line">      <span class="attr">Description:</span> <span class="type">!Sub</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">Stack</span> <span class="string">$&#123;AWS::StackName&#125;</span> <span class="string">Function</span> <span class="string">$&#123;ResourceName&#125;</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">ResourceName:</span> <span class="string">getTemplate</span></span><br><span class="line">      <span class="attr">CodeUri:</span> <span class="string">src/Function3</span></span><br><span class="line">      <span class="attr">Handler:</span> <span class="string">index.handler</span></span><br><span class="line">      <span class="attr">Runtime:</span> <span class="string">nodejs18.x</span></span><br><span class="line">      <span class="attr">MemorySize:</span> <span class="number">3008</span></span><br><span class="line">      <span class="attr">Timeout:</span> <span class="number">30</span></span><br><span class="line">      <span class="attr">Tracing:</span> <span class="string">Active</span></span><br><span class="line">      <span class="attr">Events:</span></span><br><span class="line">        <span class="attr">awesomeApiGET:</span></span><br><span class="line">          <span class="attr">Type:</span> <span class="string">Api</span></span><br><span class="line">          <span class="attr">Properties:</span></span><br><span class="line">            <span class="attr">Path:</span> <span class="string">/*</span></span><br><span class="line">            <span class="attr">Method:</span> <span class="string">GET</span></span><br><span class="line">            <span class="attr">RestApiId:</span> <span class="type">!Ref</span> <span class="string">awesomeApi</span></span><br><span class="line">      <span class="attr">Environment:</span></span><br><span class="line">        <span class="attr">Variables:</span></span><br><span class="line">          <span class="attr">BUCKET_NAME:</span> <span class="type">!Ref</span> <span class="string">templateBucket</span></span><br><span class="line">          <span class="attr">BUCKET_ARN:</span> <span class="type">!GetAtt</span> <span class="string">templateBucket.Arn</span></span><br><span class="line">      <span class="attr">Policies:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">Statement:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="attr">Effect:</span> <span class="string">Allow</span></span><br><span class="line">              <span class="attr">Action:</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObject</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObjectAcl</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObjectLegalHold</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObjectRetention</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObjectTorrent</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObjectVersion</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObjectVersionAcl</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObjectVersionForReplication</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:GetObjectVersionTorrent</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:ListBucket</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:ListBucketMultipartUploads</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:ListBucketVersions</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:ListMultipartUploadParts</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:AbortMultipartUpload</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:DeleteObject</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:DeleteObjectVersion</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:PutObject</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:PutObjectLegalHold</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:PutObjectRetention</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">s3:RestoreObject</span></span><br><span class="line">              <span class="attr">Resource:</span></span><br><span class="line">                <span class="bullet">-</span> <span class="type">!Sub</span> <span class="string">arn:$&#123;AWS::Partition&#125;:s3:::$&#123;templateBucket&#125;</span></span><br><span class="line">                <span class="bullet">-</span> <span class="type">!Sub</span> <span class="string">arn:$&#123;AWS::Partition&#125;:s3:::$&#123;templateBucket&#125;/*</span></span><br><span class="line">  <span class="attr">getTemplateLogGroup:</span></span><br><span class="line">    <span class="attr">Type:</span> <span class="string">AWS::Logs::LogGroup</span></span><br><span class="line">    <span class="attr">DeletionPolicy:</span> <span class="string">Retain</span></span><br><span class="line">    <span class="attr">Properties:</span></span><br><span class="line">      <span class="attr">LogGroupName:</span> <span class="type">!Sub</span> <span class="string">/aws/lambda/$&#123;getTemplate&#125;</span></span><br><span class="line">  <span class="attr">hogeTable:</span></span><br><span class="line">    <span class="attr">Type:</span> <span class="string">AWS::DynamoDB::Table</span></span><br><span class="line">    <span class="attr">Properties:</span></span><br><span class="line">      <span class="attr">AttributeDefinitions:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">AttributeName:</span> <span class="string">id</span></span><br><span class="line">          <span class="attr">AttributeType:</span> <span class="string">S</span></span><br><span class="line">      <span class="attr">BillingMode:</span> <span class="string">PAY_PER_REQUEST</span></span><br><span class="line">      <span class="attr">KeySchema:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">AttributeName:</span> <span class="string">id</span></span><br><span class="line">          <span class="attr">KeyType:</span> <span class="string">HASH</span></span><br><span class="line">      <span class="attr">StreamSpecification:</span></span><br><span class="line">        <span class="attr">StreamViewType:</span> <span class="string">NEW_AND_OLD_IMAGES</span></span><br><span class="line">  <span class="attr">insertHoge:</span></span><br><span class="line">    <span class="attr">Type:</span> <span class="string">AWS::Serverless::Function</span></span><br><span class="line">    <span class="attr">Properties:</span></span><br><span class="line">      <span class="attr">Description:</span> <span class="type">!Sub</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">Stack</span> <span class="string">$&#123;AWS::StackName&#125;</span> <span class="string">Function</span> <span class="string">$&#123;ResourceName&#125;</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">ResourceName:</span> <span class="string">insertHoge</span></span><br><span class="line">      <span class="attr">CodeUri:</span> <span class="string">src/Function</span></span><br><span class="line">      <span class="attr">Handler:</span> <span class="string">index.handler</span></span><br><span class="line">      <span class="attr">Runtime:</span> <span class="string">nodejs18.x</span></span><br><span class="line">      <span class="attr">MemorySize:</span> <span class="number">3008</span></span><br><span class="line">      <span class="attr">Timeout:</span> <span class="number">30</span></span><br><span class="line">      <span class="attr">Tracing:</span> <span class="string">Active</span></span><br><span class="line">      <span class="attr">Events:</span></span><br><span class="line">        <span class="attr">awesomeApiPOSTapihogesinsert:</span></span><br><span class="line">          <span class="attr">Type:</span> <span class="string">Api</span></span><br><span class="line">          <span class="attr">Properties:</span></span><br><span class="line">            <span class="attr">Path:</span> <span class="string">/api/hoges/insert</span></span><br><span class="line">            <span class="attr">Method:</span> <span class="string">POST</span></span><br><span class="line">            <span class="attr">RestApiId:</span> <span class="type">!Ref</span> <span class="string">awesomeApi</span></span><br><span class="line">      <span class="attr">Environment:</span></span><br><span class="line">        <span class="attr">Variables:</span></span><br><span class="line">          <span class="attr">TABLE_NAME:</span> <span class="type">!Ref</span> <span class="string">hogeTable</span></span><br><span class="line">          <span class="attr">TABLE_ARN:</span> <span class="type">!GetAtt</span> <span class="string">hogeTable.Arn</span></span><br><span class="line">      <span class="attr">Policies:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">DynamoDBCrudPolicy:</span></span><br><span class="line">            <span class="attr">TableName:</span> <span class="type">!Ref</span> <span class="string">hogeTable</span></span><br><span class="line">  <span class="attr">insertHogeLogGroup:</span></span><br><span class="line">    <span class="attr">Type:</span> <span class="string">AWS::Logs::LogGroup</span></span><br><span class="line">    <span class="attr">DeletionPolicy:</span> <span class="string">Retain</span></span><br><span class="line">    <span class="attr">Properties:</span></span><br><span class="line">      <span class="attr">LogGroupName:</span> <span class="type">!Sub</span> <span class="string">/aws/lambda/$&#123;insertHoge&#125;</span></span><br><span class="line">  <span class="attr">fugaFileBucket:</span></span><br><span class="line">    <span class="attr">Type:</span> <span class="string">AWS::S3::Bucket</span></span><br><span class="line">    <span class="attr">Properties:</span></span><br><span class="line">      <span class="attr">BucketName:</span> <span class="type">!Sub</span> <span class="string">$&#123;AWS::StackName&#125;-fugafileb-$&#123;AWS::AccountId&#125;</span></span><br><span class="line">      <span class="attr">BucketEncryption:</span></span><br><span class="line">        <span class="attr">ServerSideEncryptionConfiguration:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">ServerSideEncryptionByDefault:</span></span><br><span class="line">              <span class="attr">SSEAlgorithm:</span> <span class="string">aws:kms</span></span><br><span class="line">              <span class="attr">KMSMasterKeyID:</span> <span class="string">alias/aws/s3</span></span><br><span class="line">      <span class="attr">PublicAccessBlockConfiguration:</span></span><br><span class="line">        <span class="attr">IgnorePublicAcls:</span> <span class="literal">true</span></span><br><span class="line">        <span class="attr">RestrictPublicBuckets:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">fugaFileBucketBucketPolicy:</span></span><br><span class="line">    <span class="attr">Type:</span> <span class="string">AWS::S3::BucketPolicy</span></span><br><span class="line">    <span class="attr">Properties:</span></span><br><span class="line">      <span class="attr">Bucket:</span> <span class="type">!Ref</span> <span class="string">fugaFileBucket</span></span><br><span class="line">      <span class="attr">PolicyDocument:</span></span><br><span class="line">        <span class="attr">Id:</span> <span class="string">RequireEncryptionInTransit</span></span><br><span class="line">        <span class="attr">Version:</span> <span class="string">&#x27;2012-10-17&#x27;</span></span><br><span class="line">        <span class="attr">Statement:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">Principal:</span> <span class="string">&#x27;*&#x27;</span></span><br><span class="line">            <span class="attr">Action:</span> <span class="string">&#x27;*&#x27;</span></span><br><span class="line">            <span class="attr">Effect:</span> <span class="string">Deny</span></span><br><span class="line">            <span class="attr">Resource:</span></span><br><span class="line">              <span class="bullet">-</span> <span class="type">!GetAtt</span> <span class="string">fugaFileBucket.Arn</span></span><br><span class="line">              <span class="bullet">-</span> <span class="type">!Sub</span> <span class="string">$&#123;fugaFileBucket.Arn&#125;/*</span></span><br><span class="line">            <span class="attr">Condition:</span></span><br><span class="line">              <span class="attr">Bool:</span></span><br><span class="line">                <span class="attr">aws:SecureTransport:</span> <span class="string">&#x27;false&#x27;</span></span><br><span class="line">  <span class="attr">templateBucket:</span></span><br><span class="line">    <span class="attr">Type:</span> <span class="string">AWS::S3::Bucket</span></span><br><span class="line">    <span class="attr">Properties:</span></span><br><span class="line">      <span class="attr">BucketName:</span> <span class="type">!Sub</span> <span class="string">$&#123;AWS::StackName&#125;-templateb-$&#123;AWS::AccountId&#125;</span></span><br><span class="line">      <span class="attr">BucketEncryption:</span></span><br><span class="line">        <span class="attr">ServerSideEncryptionConfiguration:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">ServerSideEncryptionByDefault:</span></span><br><span class="line">              <span class="attr">SSEAlgorithm:</span> <span class="string">aws:kms</span></span><br><span class="line">              <span class="attr">KMSMasterKeyID:</span> <span class="string">alias/aws/s3</span></span><br><span class="line">      <span class="attr">PublicAccessBlockConfiguration:</span></span><br><span class="line">        <span class="attr">IgnorePublicAcls:</span> <span class="literal">true</span></span><br><span class="line">        <span class="attr">RestrictPublicBuckets:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">templateBucketBucketPolicy:</span></span><br><span class="line">    <span class="attr">Type:</span> <span class="string">AWS::S3::BucketPolicy</span></span><br><span class="line">    <span class="attr">Properties:</span></span><br><span class="line">      <span class="attr">Bucket:</span> <span class="type">!Ref</span> <span class="string">templateBucket</span></span><br><span class="line">      <span class="attr">PolicyDocument:</span></span><br><span class="line">        <span class="attr">Id:</span> <span class="string">RequireEncryptionInTransit</span></span><br><span class="line">        <span class="attr">Version:</span> <span class="string">&#x27;2012-10-17&#x27;</span></span><br><span class="line">        <span class="attr">Statement:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="attr">Principal:</span> <span class="string">&#x27;*&#x27;</span></span><br><span class="line">            <span class="attr">Action:</span> <span class="string">&#x27;*&#x27;</span></span><br><span class="line">            <span class="attr">Effect:</span> <span class="string">Deny</span></span><br><span class="line">            <span class="attr">Resource:</span></span><br><span class="line">              <span class="bullet">-</span> <span class="type">!GetAtt</span> <span class="string">templateBucket.Arn</span></span><br><span class="line">              <span class="bullet">-</span> <span class="type">!Sub</span> <span class="string">$&#123;templateBucket.Arn&#125;/*</span></span><br><span class="line">            <span class="attr">Condition:</span></span><br><span class="line">              <span class="attr">Bool:</span></span><br><span class="line">                <span class="attr">aws:SecureTransport:</span> <span class="string">&#x27;false&#x27;</span></span><br><span class="line">  <span class="attr">awesomeApi:</span></span><br><span class="line">    <span class="attr">Type:</span> <span class="string">AWS::Serverless::Api</span></span><br><span class="line">    <span class="attr">Properties:</span></span><br><span class="line">      <span class="attr">Name:</span> <span class="type">!Sub</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">$&#123;ResourceName&#125;</span> <span class="string">From</span> <span class="string">Stack</span> <span class="string">$&#123;AWS::StackName&#125;</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">ResourceName:</span> <span class="string">awesomeApi</span></span><br><span class="line">      <span class="attr">StageName:</span> <span class="string">Prod</span></span><br><span class="line">      <span class="attr">DefinitionBody:</span></span><br><span class="line">        <span class="attr">openapi:</span> <span class="string">&#x27;3.0&#x27;</span></span><br><span class="line">        <span class="attr">info:</span> &#123;&#125;</span><br><span class="line">        <span class="attr">paths:</span></span><br><span class="line">          <span class="string">/api/hoges/insert:</span></span><br><span class="line">            <span class="attr">post:</span></span><br><span class="line">              <span class="attr">x-amazon-apigateway-integration:</span></span><br><span class="line">                <span class="attr">httpMethod:</span> <span class="string">POST</span></span><br><span class="line">                <span class="attr">type:</span> <span class="string">aws_proxy</span></span><br><span class="line">                <span class="attr">uri:</span> <span class="type">!Sub</span> <span class="string">arn:$&#123;AWS::Partition&#125;:apigateway:$&#123;AWS::Region&#125;:lambda:path/2015-03-31/functions/$&#123;insertHoge.Arn&#125;/invocations</span></span><br><span class="line">              <span class="attr">responses:</span> &#123;&#125;</span><br><span class="line">          <span class="string">/api/fugas/upload:</span></span><br><span class="line">            <span class="attr">post:</span></span><br><span class="line">              <span class="attr">x-amazon-apigateway-integration:</span></span><br><span class="line">                <span class="attr">httpMethod:</span> <span class="string">POST</span></span><br><span class="line">                <span class="attr">type:</span> <span class="string">aws_proxy</span></span><br><span class="line">                <span class="attr">uri:</span> <span class="type">!Sub</span> <span class="string">arn:$&#123;AWS::Partition&#125;:apigateway:$&#123;AWS::Region&#125;:lambda:path/2015-03-31/functions/$&#123;uploadFugaFile.Arn&#125;/invocations</span></span><br><span class="line">              <span class="attr">responses:</span> &#123;&#125;</span><br><span class="line">          <span class="string">/*:</span></span><br><span class="line">            <span class="attr">get:</span></span><br><span class="line">              <span class="attr">x-amazon-apigateway-integration:</span></span><br><span class="line">                <span class="attr">httpMethod:</span> <span class="string">POST</span></span><br><span class="line">                <span class="attr">type:</span> <span class="string">aws_proxy</span></span><br><span class="line">                <span class="attr">uri:</span> <span class="type">!Sub</span> <span class="string">arn:$&#123;AWS::Partition&#125;:apigateway:$&#123;AWS::Region&#125;:lambda:path/2015-03-31/functions/$&#123;getTemplate.Arn&#125;/invocations</span></span><br><span class="line">              <span class="attr">responses:</span> &#123;&#125;</span><br><span class="line">      <span class="attr">EndpointConfiguration:</span> <span class="string">REGIONAL</span></span><br><span class="line">      <span class="attr">TracingEnabled:</span> <span class="literal">true</span></span><br><span class="line">      <span class="attr">Auth:</span></span><br><span class="line">        <span class="attr">Authorizers:</span></span><br><span class="line">          <span class="attr">awesomeAuthorizer:</span></span><br><span class="line">            <span class="attr">UserPoolArn:</span> <span class="type">!GetAtt</span> <span class="string">awesomeUserPool.Arn</span></span><br><span class="line">  <span class="attr">awesomeUserPool:</span></span><br><span class="line">    <span class="attr">Type:</span> <span class="string">AWS::Cognito::UserPool</span></span><br><span class="line">    <span class="attr">Properties:</span></span><br><span class="line">      <span class="attr">AdminCreateUserConfig:</span></span><br><span class="line">        <span class="attr">AllowAdminCreateUserOnly:</span> <span class="literal">false</span></span><br><span class="line">      <span class="attr">AliasAttributes:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">email</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">preferred_username</span></span><br><span class="line">      <span class="attr">UserPoolName:</span> <span class="type">!Sub</span> <span class="string">$&#123;AWS::StackName&#125;-awesomeUserPool</span></span><br></pre></td></tr></table></figure>

</div></details>

<h3 id="やってみた感想">やってみた感想</h3><p>とにかくお手軽なことに驚きました。上述の <strong>やってみた</strong> はスクリーンショットを撮る時間を除けば5分も掛からなかったため、タイポに苦しみながら手書きするのと比べると雲泥の差を感じました。また、環境構築が不要＋GUIだけで完結できるため、今後思い立った時にサクッと作れちゃうなと引き出しを増やすことが出来ました。</p>
<p>一方で、上述の構成に例えばCloudFrontを追加したいと思った時にApplication Composerだけではできないため、やはり”型にハマれば強い”系のサービスではあるなと思いました。</p>
<h2 id="おわりに">おわりに</h2><p>最後まで読んでいただきありがとうございました。</p>
<p>今後も新しめの情報に目を光らせ、興味が沸いたらまた記事にしようと思います。</p>
<p>では、Futureの春の入門祭りはまだまだ続きますということで、次回担当の 高世駿 さんの 正規表現入門 です。</p>
]]></content>
    <summary type="html">2023/03/07から一般提供が開始された新サービス「AWS Application Composer」を使ってみて、どんな人向けか、強み・弱みは何かというところを見ていきます。</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="AWS" scheme="https://future-architect.github.io/tags/AWS/"/>
    <category term="サーバーレス" scheme="https://future-architect.github.io/tags/%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%83%AC%E3%82%B9/"/>
    <category term="ノーコード" scheme="https://future-architect.github.io/tags/%E3%83%8E%E3%83%BC%E3%82%B3%E3%83%BC%E3%83%89/"/>
  </entry>
  <entry>
    <title>Google Cloudのしくみと技術がしっかりわかる教科書を読んだ感想</title>
    <link href="https://future-architect.github.io/articles/20230302a/"/>
    <id>https://future-architect.github.io/articles/20230302a/</id>
    <published>2023-03-01T15:00:00.000Z</published>
    <updated>2023-03-01T15:00:00.000Z</updated>
    <author><name>藤戸四恩</name></author>
    <content type="html"><![CDATA[<h2 id="はじめに">はじめに</h2><p>金融グループ所属、新人の藤戸四恩です。<br>インデックス記事に書かせていただきましたが、積読消化目的で参加させていただきました。<br><img fetchpriority="high" src="/images/2023/20230302a/image.png" alt="" width="400" height="564"></p>
<p>読書感想文連載 の8冊目は、技術評論社から出版されている 図解即戦力 Google Cloudのしくみと技術がこれ1冊でしっかりわかる教科書 です。</p>
<p>この書籍を選んだ理由としては、CCoE(クラウド活用推進組織)メンバーに参加しGoogle Cloud に触れる機会があったのですが、いままではCloudというものに触れてこなかったため全体像を掴みたいと考えたからです。</p>
<p>気になったところについて感想を書いていきたいと思います。</p>
<h2 id="書籍の概要">書籍の概要</h2><p>この書籍は2021年9月3日に発売された本で、Google Cloudに関する基本的な知識を学ぶことができます。<br>下記の通り10章から構成されています。</p>
<ul>
<li>1章 Google Cloud の基礎知識</li>
<li>2章 クラウドの仕組みとGoogleの取り組み</li>
<li>3章 Google Cloud を使うには</li>
<li>4章 サーバーサービス「Compute Engine」</li>
<li>5章 ネットワークサービス「VPC」</li>
<li>6章 ストレージサービス「Cloud Storage」</li>
<li>7章 コンテナとサーバーレスのサービス</li>
<li>8章 データベースサービス</li>
<li>9章 データ分析のサービス</li>
<li>10章 そのほかに知っておきたい Google Cloud のサービス</li>
</ul>
<h2 id="Google-Cloudのシェア率と検索比率について">Google Cloudのシェア率と検索比率について</h2><p>書籍内の内容ではないですが、読み進めるにあたり、Google Cloud がどれくらいのシェアがあるのか気になり、調べてみました。</p>
<p>Publickey社の記事内では<sup id="fnref:1">1</sup>、Canalys社が調査した、2022年度第2四半期時点のクラウドのシェア率について記載されており、AWS が31％で1位、 Azure が24％で2位、Google Cloud が8％が記載されています。<sup id="fnref:2">2</sup></p>
<p>また、Googleでの検索比率を Google Trends でそれぞれのクラウドサービス名を検索しました。<br>比較したクラウドサービスは、Amazon Web Services (以下AWS)、Microsoft Azure (以下Azure)、Google Cloudの3つです。</p>
<p>※Google Cloud は2022年6月に Google Cloud Platform から Goolge Cloud に名称変更されたため、Google Cloud Platform をトピックにいれています。</p>
<img src="/images/2023/20230302a/スクリーンショット_2023-02-27_19.54.39.png" alt="" width="1160" height="686" loading="lazy">

<p>個人的には、Google Cloud のシェアが思っていたよりも低く驚きました。</p>
<h2 id="ライブマイグレーションについて">ライブマイグレーションについて</h2><p>4章 サーバーサービス「Compute Engine」の障害発生時の対応（1）~ライブマイグレーション(p.92)でCompute Engine の障害発生時の対応方法についての説明があり、対応方法の1つとして<code>ライブマイグレーション</code>が紹介されています。</p>
<blockquote>
<p>Compute Engineは、ハードウェアを購入することなくオンデマンドで仮想マシンを利用できるコンピューティングサービスです。<br>Compute Engineでは仮想マシンが、仮想マシンを実行するためのソフトウェアであるハイパーバイザ上で複数実行されます。</p>
</blockquote>
<p>Compute Engineは仮想マシンのことで、AWSだとAmazon EC2、AzureだとAzure Virtual Machineのことです。</p>
<blockquote>
<p>ComputeEngineには障害発生時の対応として、ライブマイグレーションとホストエラー対応という、大きく2つの機能が備わっています。<br>ライブマイグレーションとは、仮想マシンを稼働した状態のまま、仮想マシンを実行する物理サーバを別の物理サーバに移動する仕組みです。</p>
</blockquote>
<p><code>ライブマイグレーション</code>という単語は初めて知ったのですが、　Compute Engineはどのようにライブマイグレーションを実現しているのか調べてみました。<sup id="fnref:3">3</sup></p>
<img src="/images/2023/20230302a/image_2.png" alt="" width="875" height="661" loading="lazy">
※ライブマイグレーションのコンポーネントの図を引用<sup id="fnref:3">3</sup>

<p>VMの移行は3つのステップで行われます。</p>
<ol>
<li>VM上のメモリやディスクを移行先のVMにコピーします。</li>
<li>移行元のVMは停止し、1でコピーしたメモリの差分を移行先にコピーします。</li>
<li>VMが移行先のVMで実行されます。</li>
</ol>
<p>移行が完了すると、移行元のVMが削除されることによって実現されます。<br>Google Cloud は障害を事前検知しているため<sup id="fnref:4">4</sup>、検知した際にライブマイグレーションに影響がない場合は、上記のようなライブマイグレーションで障害対応をしていることがわかりました。</p>
<h3 id="BigQuery-と-RDB-の違い">BigQuery と RDB の違い</h3><p>9章 データ分析のサービスのBigQueryとRDBの違い(p.253)で下記の記載があります。</p>
<blockquote>
<p>BigQueryは、RDB同様にテーブルを持ち、SQLによってデータの処理要求を行います。<br>では、どのような点がRDBと異なるのでしょうか。<br>1つ目は、カラム型ストレージである点です。必要なカラムにのみアクセスできるため、データ走査を最小化できます。<br>2つ目は、ツリーアーキテクチャである点です。クライアントから受け取ったクエリの処理をツリー構造の処理に分解して、複数のサーバーに分散することで、大規模な分散処理を実現しています。<br>…..<br>BigQueryはSQLの構文をサポートしつつ、NoSQLの特徴を併せ持つハイブリットなシステムといえます。</p>
</blockquote>
<p>2022年11月18日に開催された国際度量衡総会では新しい単位ロナ(ronna)10の27乗とクエタ(quetta)10の30乗が追加された<sup id="fnref:5">5</sup>ことからも<br>データ量はどんどん大規模になっていて、大規模なデータを高速で処理する必要性はどんどん増しているように感じています。</p>
<p>カラム型ストレージ(列指向)とツリーアーキテクチャは、どのような仕組みか気になったため、調べてみました。</p>
<p>理由の1つ目のカラム型ストレージについては、弊社の2021年に開催された、春の入門連載2021の4日目の<code>IT初学者がカラムナデータベースを勉強してみた</code>で解りやすく解説されていました。<sup id="fnref:6">6</sup><br>つまりカラム型ストレージは、データを列方向に保持するとデータの定義情報(型など)や値が同一のデータを格納しているため圧縮効率が高いため高速化されていることがわかりました。</p>
<p>理由の2つ目のツリーアーキテクチャは、クエリをRootServer、MixerServer、LeafServerの順にツリー構造分解されることにより分散処理を実行することで高速されています。<sup id="fnref:7">7</sup></p>
<p>これらによりBigQueryは大規模なデータを効率よく処理されています。</p>
<h2 id="おわりに">おわりに</h2><p>図解即戦力 Google Cloudのしくみと技術がこれ1冊でしっかりわかる教科書の読書感想文でした。</p>
<p>クラウドサービスを触ったことがなかった自分でも躓くことなく読み進めることができました。<br>Google Cloudを使用する上で基礎的な知識を学ぶことができたと思います。<br>クラウドサービスを触ったことがなく、Google Cloudをこれから使う方にはぜひ手に取ってみてください。</p>
<p>明日の読書感想連載は工藤さんのSQLアンチパターンです。</p>
<div id="footnotes"><hr><div id="footnotelist"><ol style="list-style:none; padding-left: 0;"><li id="fn:1"><span style="vertical-align: top; padding-right: 10px;">1.</span><span style="vertical-align: top;">https://www.publickey1.jp/blog/22/202221aws2azure3google_cloud3.html</span> ↩</li><li id="fn:2"><span style="vertical-align: top; padding-right: 10px;">2.</span><span style="vertical-align: top;">https://www.canalys.com/newsroom/global-cloud-services-Q2-2022</span> ↩</li><li id="fn:3"><span style="vertical-align: top; padding-right: 10px;">3.</span><span style="vertical-align: top;">https://cloud.google.com/compute/docs/instances/live-migration-process?hl=ja</span> ↩</li><li id="fn:4"><span style="vertical-align: top; padding-right: 10px;">4.</span><span style="vertical-align: top;">https://cloud.google.com/support/docs/dashboard?hl=ja#lifecycle_of_an_incident</span> ↩</li><li id="fn:5"><span style="vertical-align: top; padding-right: 10px;">5.</span><span style="vertical-align: top;">https://www.asahi.com/articles/ASQCL441NQC6ULBH006.html</span> ↩</li><li id="fn:6"><span style="vertical-align: top; padding-right: 10px;">6.</span><span style="vertical-align: top;">https://future-architect.github.io/articles/20210419b/</span> ↩</li><li id="fn:7"><span style="vertical-align: top; padding-right: 10px;">7.</span><span style="vertical-align: top;">https://tech.plaid.co.jp/inside_bigquery</span> ↩</li></ol></div></div>]]></content>
    <summary type="html">積読消化目的で参加させていただきました。図解即戦力 Google Cloudのしくみと技術がこれ1冊でしっかりわかる教科書を選んだ理由としては、CCoEメンバーに参加しGoogle Cloud に触れる機会があったのですが、いままではCloudというものに触れてこなかったため掴みたいと考えたからです</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="BigQuery" scheme="https://future-architect.github.io/tags/BigQuery/"/>
    <category term="GoogleCloud" scheme="https://future-architect.github.io/tags/GoogleCloud/"/>
    <category term="入門" scheme="https://future-architect.github.io/tags/%E5%85%A5%E9%96%80/"/>
    <category term="書評" scheme="https://future-architect.github.io/tags/%E6%9B%B8%E8%A9%95/"/>
  </entry>
  <entry>
    <title>Azure Data Boxを使ってみた</title>
    <link href="https://future-architect.github.io/articles/20221108a/"/>
    <id>https://future-architect.github.io/articles/20221108a/</id>
    <published>2022-11-07T15:00:00.000Z</published>
    <updated>2022-11-07T15:00:00.000Z</updated>
    <author><name>一ノ瀬秀都</name></author>
    <content type="html"><![CDATA[<h2 id="はじめに">はじめに</h2><p>はじめまして、テクノロジーイノベーショングループ所属、2021年4月に新卒で入社した一ノ瀬です。</p>
<p>秋のブログ週間の6本目となる本記事では、オンプレからクラウドへのデータ移行に関して、AzureのData Boxというサービスを利用する機会があったので、詳細なワークフローや失敗談について共有します。</p>
<p>昨今のDX推進の流れにのり、システムのクラウドシフト&#x2F;リフトに取り組む方も多いかと思います。</p>
<p>「クラウドへの移行を考えているがデータ量が膨大で移行ができない」といった悩みがあったり、「クラウドへのデータ移行でData Boxサービスを利用したい！ けど、よくわからない…」という方々に本記事を参考にしていただけると幸いです。</p>
<h2 id="Data-Boxを利用する背景">Data Boxを利用する背景</h2><p>今回の要件は、オンプレのデータ分析基盤で収集していた100TB以上のデータをAzureに移行することでした。</p>
<p>当初はAzure専用線を使ったオンラインのデータ移行を検討していました。</p>
<p>しかし、データ容量の大きさから移行に約7ヶ月かかる点からオンラインのデータ移行は断念しました。</p>
<p>短期間かつNW負荷が低くてすむ移行方法はないか？ ということで、オンプレ基盤とAzure間でオフラインでデータ移行できるサービスData Boxを利用することになりました。</p>
<p>続いては、動作環境に触れていきます。</p>
<h2 id="動作環境のはなし">動作環境のはなし</h2><h3 id="物理構成はどんな感じ？">物理構成はどんな感じ？</h3><p>データコピー時の登場人物は以下の計3端末です。</p>
<ol>
<li>Data Box</li>
<li>Data Box初期設定用PC</li>
<li>データコピー用サーバ</li>
</ol>
<img fetchpriority="high" src="/images/2022/20221108a/WS000297.JPG" alt="WS000297.JPG" width="1037" height="736">

<p>Data Box初期設定用PCとデータコピー用サーバは今回の案件のために用意したので、以下に環境情報を記します。<br>転送先はAzure Data Boxの領域であり、また転送元はユーザにより異なるため環境情報の説明は省きます。</p>
<p><strong>データコピー用サーバ</strong></p>
<ul>
<li>Red Hat Enterprise for Linux v8.4</li>
<li>メモリ16GB</li>
<li>1CPU4コア</li>
</ul>
<p><strong>Data Box初期設定用PC</strong>（※）</p>
<ul>
<li>Windows10</li>
<li>Google Chrome(2022&#x2F;8&#x2F;18時点最新)</li>
</ul>
<p>※借用PCのため詳細不明</p>
<h3 id="Data-Boxの結線の詳細は？">Data Boxの結線の詳細は？</h3><p>Data Boxの結線についても紹介します。<br>今回の構成では、以下の組み合わせで結線しています。</p>
<div class="scroll"><table>
<thead>
<tr>
<th align="left">Data Boxのポート</th>
<th align="left">接続先</th>
<th align="left">種別</th>
<th align="left">ポートの説明</th>
</tr>
</thead>
<tbody><tr>
<td align="left">MGMTポート</td>
<td align="left">Data Box初期設定用PC</td>
<td align="left">RJ45</td>
<td align="left">初期設定時のみ使用<br>データコピーでは使用しない</td>
</tr>
<tr>
<td align="left">Data#1~2ポート</td>
<td align="left">10GbE対応のL2スイッチ</td>
<td align="left">10GBASE-SR</td>
<td align="left">データコピーにて<br>メインで使用する</td>
</tr>
<tr>
<td align="left">Data#3ポート</td>
<td align="left">1GbE対応のL2スイッチ</td>
<td align="left">RJ45</td>
<td align="left">アクセスは発生させない<br>前提条件を満たすために結線</td>
</tr>
</tbody></table></div>
<p>以下は結線のイメージです。<br><img src="/images/2022/20221108a/image.png" alt="" width="820" height="449" loading="lazy"><br>出典：Azure Data Boxの配線方法</p>
<p>今回MGMTポート + Data#1~3ポート全てで結線をしている理由は、サービス利用の前提として調達・結線が求められているためです。</p>
<p>Docs:DataBoxのクイックスタートの前提条件の1つに以下の記述があります。</p>
<blockquote>
<p>Data Box をホスト コンピューターに接続するために以下のケーブルを用意していること。<br>・10 GbE SFP+ Twinax 銅線ケーブル 2 本 (DATA 1、DATA 2 ネットワーク インターフェイスで使用)<br>・RJ-45 CAT 6 ネットワーク ケーブル 1 本 (MGMT ネットワーク インターフェイスで使用)<br>・RJ-45 CAT 6A OR ネットワーク ケーブル 1 本、RJ-45 CAT 6 ネットワーク ケーブル 1 本 (それぞれ 10 Gbps または 1 Gbps として構成されている DATA 3 ネットワーク インターフェイスで使用)</p>
</blockquote>
<p>また、Microsoftサポートから以下コメントを頂いています。</p>
<blockquote>
<p>Docsにて「必要」と記載のある部材に関しては原則調達をお願いしております。<br>仮に上記が欠けている場合、有事の際にサービス提供者側としての責任を負うことが出来ないという判断になる懸念がございます。</p>
</blockquote>
<p>以上から、Microsoft社はケーブルを4本全て用意し、Data Boxのすべてのポートを接続させた状態で使用することを前提にしているようです。</p>
<p>最低限の構成（例：Data#1とMGMTのみ）でも動作はするかと思いますが、今回は万全を期すために、MGMT + Data#1~3ポート全てで結線をしています。</p>
<p>また結線に使用したケーブルやアダプターについても説明します。</p>
<p>SFP+アダプターにはCiscoの「SFP-10G-SR」という機種を使用しました。<br>SFP+アダプターについては、問い合わせを起票してMiceosoftサポートが推奨する機種を参考に選びました。<br>以下サポートからの回答です。</p>
<blockquote>
<p>Mellanox ConnectX-3 Firmware Release Notesの「1.2.1 Validated and Supported 1GbE&#x2F;10GbE Cables (p.8~11)」に記載されているケーブルと同等のケーブルであれば問題なく動作すると考えられます。</p>
</blockquote>
<p>RJ45は一般的なLANケーブルで問題ないですが、SFP+のアダプターは小さくても高額ですので、「アダプター準備したけど使えないじゃん」という事態を避けるためにも慎重に準備することをおすすめします。</p>
<h2 id="Data-Boxの主なワークフロー">Data Boxの主なワークフロー</h2><p>では、実際の利用の流れを説明していこうと思います。</p>
<p>Data Boxを使ったデータ移行の大まかな流れは以下です。</p>
<img src="/images/2022/20221108a/WS000294.JPG" alt="WS000294.JPG" width="1200" height="176" loading="lazy">

<ol>
<li>発注</li>
<li>受け取り</li>
<li>デバイス初期設定</li>
<li>結線とマウント</li>
<li>データコピー</li>
<li>返送</li>
<li>Azureへインポート</li>
</ol>
<p>※今回の案件では筐体の写真を撮影できませんでした。手順の中で写真なしで筐体の説明をしていますが、ご了承ください。</p>
<h2 id="発注">発注</h2><img src="/images/2022/20221108a/ワークフロー_(1).JPG" alt="ワークフロー_(1).JPG" width="1200" height="179" loading="lazy">

<h3 id="注文の作成">注文の作成</h3><p>まずはAzure Portalにログインし、ダッシュボードからData Boxを発注していきます。</p>
<p>Azure Portalのホーム画面で[Azure Data Box]を選択し、画面左上の[作成]を押下します。</p>
<img src="/images/2022/20221108a/DataBox発注1.jpg" alt="DataBox発注1.jpg" width="1200" height="399" loading="lazy">

<p>次の画面では対象のサブスクリプション、リソースグループ、ソースの国、宛先のAzureリージョンを選択し、[適用]を押下します。</p>
<img src="/images/2022/20221108a/DataBox発注2.jpg" alt="DataBox発注2.jpg" width="1200" height="442" loading="lazy">

<img src="/images/2022/20221108a/DataBox発注3.jpg" alt="DataBox発注3.jpg" width="1200" height="605" loading="lazy">

<p>サービスを選択すると、注文に関する記入する画面に移ります。</p>
<p>[基本]では注文名を指定します。</p>
<p>ここで設定する注文名は、Azure Portalに残るものですので、複数台発注する場合は特に一意な名称にしておくとよいでしょう。</p>
<img src="/images/2022/20221108a/DataBox発注4.jpg" alt="DataBox発注4.jpg" width="1200" height="300" loading="lazy">

<p>注文名を指定したら[データ格納先]に移動します。データの格納先と宛先のAzureリージョン、データをインポート&#x2F;エクスポートしたいストレージアカウントを選択します。</p>
<img src="/images/2022/20221108a/DataBox発注5.jpg" alt="DataBox発注5.jpg" width="1200" height="531" loading="lazy">

<p>Data Boxサービスは一部のストレージアカウントのタイプをサポートしていないため、発注に先立って確認しておくと良いでしょう。</p>
<ul>
<li>Docs:インポートでサポートされているストレージアカウント</li>
<li>Docs:エクスポートでサポートされているストレージアカウント</li>
</ul>
<p>今回はGeneral-purpose(汎用) v2 Standardを使用しています。</p>
<p>次は[セキュリティ]です。</p>
<p>デバイスのロック解除兼Web UIのログインに使用するパスワードの種類を設定します。Microsoftマネージドキーかカスタマーマネージドキーを選択できます。</p>
<p>今回は全項目でMicrosoftマネージドキーを選択していますが、カスタマーマネージドキーを選択すると、より長く複雑なパスワードを設定できるようです。パスワードセキュリティをより強固にしたい場合は選択するとよいでしょう。</p>
<img src="/images/2022/20221108a/DataBox発注6.jpg" alt="DataBox発注6.jpg" width="1200" height="547" loading="lazy">

<p>[連絡先の詳細]では出荷方法と通知を受け取るメールアドレス、（Microsoftの管理による出荷を選択した場合は）配達先住所の設定をします。</p>
<p>今回は自己管理の出荷を選択しています。メールはメーリングリストも使用可能です。</p>
<img src="/images/2022/20221108a/住所の追加.jpg" alt="住所の追加.jpg" width="1200" height="567" loading="lazy">

<p>[タグ]では対象の注文にタグを設定できます。請求情報等の管理のために便利な機能のようですが、今回は空欄としています。</p>
<img src="/images/2022/20221108a/DataBox発注9.jpg" alt="DataBox発注9.jpg" width="1200" height="324" loading="lazy">

<p>必要なすべての項目を記入し終えたら[確認と注文]に移動し発注します。</p>
<h2 id="受け取り">受け取り</h2><img src="/images/2022/20221108a/ワークフロー_(2).JPG" alt="ワークフロー_(2).JPG" width="1200" height="178" loading="lazy">

<h3 id="受取日の調整">受取日の調整</h3><p>次はData Box受取日の調整をします。<br>今回は自己管理の出荷を選択したため、受け取り・引き渡しの両方で自己管理の出荷を前提に説明していきます。</p>
<p>まずはadbops@microsoft.com宛てに必要な情報をメールで送付します。件名を <code>Request Azure Data Box Pickup for Order: \&lt;ordername&gt;</code> に設定し、本文には以下フォーマットを記入したものを記入します。今回は日本語で記入しました。</p>
<p>Company name (会社名):<br>Contact name (受取担当者名):<br>Contact tel. no. (受取担当者電話番号):<br>Date of pickup (受取日):<br>Date of birth (担当者生年月日):<br>Nationality (担当者国籍):<br>Time of pickup (受取時刻):<br>Car number plate (自動車登録番号):</p>
<p>また、希望受取日は、複数決めておくとその後の調整がスムーズです。私が利用した際は、Microsoftから日程変更の依頼が来ました。</p>
<p>受取日が決定すると、Azure Portalで認証コードが発行され、azure-noreply@microsoft.comから受取準備が完了した旨のメール（以下、参照）が送付されます。</p>
<img src="/images/2022/20221108a/受け取り準備完了メール.JPG" alt="受け取り準備完了メール.JPG" width="511" height="529" loading="lazy">

<p>受取当日は以下3点を用意し、指定された住所でData Boxを受け取ります。</p>
<ol>
<li>認証コード</li>
<li>受取準備完了メールのコピー</li>
<li>受取担当者の写真つき身分証明書の</li>
</ol>
<p>認証コードについては、Microsoft側担当者に口頭で伝える必要があるため、メモ等を用意しておくと良いでしょう。</p>
<p>事前に知らなかったのですが、Databoxの受け取り・引き渡しの際、いくつかの書類（NDA等）にサインをする必要があります。NDAは個人とMicrosoft者の間で締結するもので、データセンターの情報などの漏洩防止に関係しているようです。</p>
<p>無事受け取れたら、いよいよData Boxの初期設定に移ります。</p>
<h2 id="デバイスの初期設定">デバイスの初期設定</h2><img src="/images/2022/20221108a/ワークフロー_(3).JPG" alt="ワークフロー_(3).JPG" width="1200" height="179" loading="lazy">

<h3 id="開梱">開梱</h3><p>Microsoft社から引き取った段ボールを開梱し筐体を取り出したら、次はData Boxの起動と初期設定作業に移ります。<br>Docs:機能と仕様にありますが、Data Boxの重さは23Kg、サイズは309.0 mm x 430.4 mm x 502.0 mmです。</p>
<p>大人一人でギリギリ設置可能な大きさ・重さですが、複数名で行うとより安全でしょう。</p>
<h3 id="Data-Boxの起動">Data Boxの起動</h3><p>まず、ディスプレイとは反対側に位置する扉を開け、電源ケーブルを取り出します。<br>電源ケーブルをデバイスと電源に接続し、ディスプレイの下にある電源ボタンを押し、Data Boxを起動します。</p>
<h3 id="Web-UIへアクセス">Web UIへアクセス</h3><p>次にData BoxのWeb UIに Data Box初期設定用PCからアクセスしていきます。</p>
<p>まず Data Box初期設定用PCにIPアドレスを割り当てていきます。Data Box初期設定用PCのイーサネットアダプタのIPアドレスを192.168.100.5&#x2F;24に設定し、Data BoxのMGMTポートと Data Box初期設定用PCをLANケーブルを結線します。</p>
<p>結線したら、 Data Box初期設定用PCでブラウザを開き、https:&#x2F;192.168.10.10にアクセスし、ログイン画面が表示されれば疎通成功です。</p>
<p>次にAzurePortalに記載されているデバイスロックのパスワードを入力してWeb UIにログインします。</p>
<p>※イーサネットに割り当てるIPアドレスや、Web UIのURLはDocs:デバイスに接続するを参考にしています。</p>
<p>おまけではありますが、ここでデバイスの実効容量の確認も済ませると良いです。</p>
<p>ログイン後に表示されるダッシュボード中央の[Connect and copy]にて、その時点の空き容量（Free Space）と使用済み容量（Used Space）が表示されます。<br>※キャプチャはデータコピー最中のものです。</p>
<img src="/images/2022/20221108a/【1号機】ダッシュボード.jpg" alt="【1号機】ダッシュボード.jpg" width="1200" height="583" loading="lazy">

<p>一通りコピーした後に「思ったよりファイル置けなかった」「もっとコピーしておけばよかった」という事態を避けるため、事前に実効容量を確認し、コピー計画の最終確認ができると良いです。</p>
<p>今回の実効容量は、2台とも80TBにほど近い値でした。100GB程度の個体差はありましたが、ほとんど気にならない差でした。Docs:実効容量では80TBとされていますが、ほぼ正確な値と思って良さそうです。</p>
<p>次にData Box側の初期設定をします。</p>
<p>今回の手順では、Data#1~3ポートへのIPアドレス割り当てとNFSの接続許可設定をしていきます。</p>
<h3 id="Data-BoxへのIP割り当て">Data BoxへのIP割り当て</h3><p>まず、IPアドレス割り当てからです。</p>
<p>[Set network interfaces]ページからネットワーク設定画面に遷移し、Data＃1〜3ポートにIPアドレスを割り当てます。</p>
<p>今回は3つのポートすべてにIPを割り当てていきます。</p>
<p>※この際MGMTポートのIPアドレスは変更できないため注意です。</p>
<img src="/images/2022/20221108a/【1号機】NWインターフェース設定.jpg" alt="【1号機】NWインターフェース設定.jpg" width="1200" height="587" loading="lazy">

<p>今回は静的にIPアドレスを割り当てるので、IP setteingsをStaticに設定し、ほかの項目（IP address, Subnet, Gateway）を埋めました。</p>
<p>任意のポートでIPアドレスを入力したら、画面左下の[Apply settings]を押下します。</p>
<p>ダッシュボードに戻り、設定したIPが各ポートで反映されていれば設定完了です。</p>
<h3 id="データコピーの接続許可設定">データコピーの接続許可設定</h3><p>次にデータコピーに必要な接続情報を取得・設定します。</p>
<p>ダッシュボードから[Connect and copy]ページを選択した後、対象のストレージアカウントで転送に使用するプロトコルを選択します。今回はCIFSを利用するため、[SMB]を押下します。</p>
<p>押下すると、添付のようなポップアップが表示されます。</p>
<p>ここでCIFS接続に必要なユーザネーム、パスワードを取得できます。</p>
<img src="/images/2022/20221108a/【1号機】接続とコピー_SMB.jpg" alt="【1号機】接続とコピー_SMB.jpg" width="1200" height="585" loading="lazy">

<p>CIFSに限らず、「NFSもしくはREST APIで転送したい！」と考えている方も、[Connect and copy]ページにて同様に接続情報を取得・設定できます。</p>
<p>NFSの場合は接続許可したいIPアドレスをテキストボックスに記入し、Validata IP addressを押下します。</p>
<p>IPが追加されれば、エクスポート設定が完了します。</p>
<img src="/images/2022/20221108a/【1号機】接続とコピー_NFS.jpg" alt="【1号機】接続とコピー_NFS.jpg" width="1200" height="582" loading="lazy">

<p>REST APIの場合は、BLOBエンドポイントのURL、また認証情報であるAPI Keyや Connection Stringが取得できます。</p>
<img src="/images/2022/20221108a/【1号機】接続とコピー_RESTAPI.jpg" alt="【1号機】接続とコピー_RESTAPI.jpg" width="1200" height="582" loading="lazy">

<h2 id="結線とマウント">結線とマウント</h2><img src="/images/2022/20221108a/ワークフロー_(4).JPG" alt="ワークフロー_(4).JPG" width="1200" height="179" loading="lazy">

<h3 id="Data-BoxとNWスイッチの結線">Data BoxとNWスイッチの結線</h3><p>Data BoxへのIP割り当てとデータコピーの接続設定が済んだので、<br>ついにData BoxとNWスイッチを結線させ、ネットワークに接続していきます（やったー）</p>
<p>接続するポートとスイッチの対応や、ケーブルの規格については物理環境のはなしの中のData Boxの結線の詳細は？を参照ください。</p>
<h3 id="Data-Boxのネットワーク接続確認">Data Boxのネットワーク接続確認</h3><p>Data Boxをネットワークに接続させたら、 Data Box初期設定用PCでData Boxにアクセスします。<br>Data Box初期設定用PCのブラウザーからhttps:&#x2F;{Data＃1〜3ポートに割り当てたIP}にアクセスし、Web UIのログイン画面が表示されれば疎通成功です。</p>
<p>デバイスがネットワークに接続したことが確認できたら、以上でデバイス側での事前作業は完了です（やったー）</p>
<p>次にデータコピー用サーバでの作業です。</p>
<p>この手順ではData Boxのファイルシステムマウントとファイルコピーの動作確認を行います。</p>
<h3 id="Data-Boxのマウント">Data Boxのマウント</h3><p>まずデータコピー用サーバにログインし、<code>/etc/fstab</code> にData BoxをNFSマウントするための定義を記入していきます。</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">$ vim /etc/fstab</span><br><span class="line"></span><br><span class="line">=====以下定義を追加=====</span><br><span class="line"><span class="comment"># Data Box</span></span><br><span class="line">\\&lt;DeviceIPAddress#1&gt;\&lt;storageaccountname_BlockBlob&gt;   /mnt/databox1 cifs rw,username=&lt;username&gt;,password=&lt;password&gt;,uid=&lt;uid&gt;,gid=&lt;gid&gt;,dir_mode=0777,file_mode=0777  0 0</span><br><span class="line">\\&lt;DeviceIPAddress#2&gt;\&lt;storageaccountname_BlockBlob&gt;  /mnt/databox2 cifs rw,username=&lt;username&gt;,password=&lt;password&gt;,uid=&lt;uid&gt;,gid=&lt;gid&gt;,dir_mode=0777,file_mode=0777 0 0</span><br><span class="line">=======================</span><br></pre></td></tr></table></figure>

<p><code>/etc/fstab</code> ファイルへの書き込みが完了したら、ついにData Boxをマウントしていきます。<br>対象ファイルシステムが正しくマウントされたかも同時に確認していきます。</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">$ mount /mnt/databox1</span><br><span class="line">$ mount /mnt/databox2</span><br><span class="line"></span><br><span class="line">$ <span class="built_in">df</span> -h</span><br><span class="line">ファイルシステム                                        サイズ  使用  残り 使用% マウント位置</span><br><span class="line">\\&lt;DeviceIPAddress#1&gt;\&lt;storageaccountname_BlockBlob&gt;          79T  135G   79T    1% /mnt/databox1</span><br><span class="line">\\&lt;DeviceIPAddress#2&gt;\&lt;storageaccountname_BlockBlob&gt;          79T   96G   79T    1% /mnt/databox2</span><br></pre></td></tr></table></figure>

<h3 id="マウントポイント配下にディレクトリ作成">マウントポイント配下にディレクトリ作成</h3><p>次にマウントポイント配下にディレクトリを作成していきます。Data Boxのファイルシステムにデフォルトで備わっているディレクトリは<code>\&lt;storageaccountname_BlockBlob&gt;</code> の1つのみでData Boxを発注したストレージアカウント名がそのままディレクトリ名になっています。</p>
<blockquote>
<p>常にコピーしようとするファイル用のフォルダーを共有下に作成してから、ファイルをそのフォルダーにコピーします。<br>~~~中略~~~<br>ストレージ アカウント内の root フォルダーに直接ファイルをコピーすることはできません。</p>
</blockquote>
<p>Docs:Data Boxに接続するで推奨されているように、デフォルトのディレクトリの1階層下に新たなディレクトリ（以下、コンテナー用ディレクトリ）を作成し、そこにデータをコピーする必要があります。</p>
<blockquote>
<p>ブロック BLOB およびページ BLOB の共有の下に作成したフォルダーは、データが BLOB としてアップロードされるコンテナーになります。</p>
</blockquote>
<p>また、<code>\&lt;storageaccountname_BlockBlob&gt;</code> の直下に作成したディレクトリは、Azureへインポート後にコンテナーとして反映されます。<br>今回はデフォルトのコンテナー配下にファイル及びディレクトリを配置する想定だったため、以下手順でディレクトリを作成していきます。</p>
<p>※Data Boxを2台同時に使用するため、管理上の都合でコンテナ用ディレクトリ配下に更に1階層ディレクトリを作成していますが、特に必要ではありません。<br>ユーザー&#x2F;オーナーは…</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">$ <span class="built_in">mkdir</span> -m 755 /mnt/databox1/&lt;containername&gt;</span><br><span class="line">$ <span class="built_in">mkdir</span> -m 755 /mnt/databox2/&lt;containername&gt;</span><br><span class="line"></span><br><span class="line">$ <span class="built_in">mkdir</span> -m 755 /mnt/databox1/&lt;containername&gt;/databox1</span><br><span class="line">$ <span class="built_in">mkdir</span> -m 755 /mnt/databox2/&lt;containername&gt;/databox2</span><br><span class="line">$ find /mnt/databox* -<span class="built_in">ls</span></span><br><span class="line">3458764513820542746      1 drwxrwxr-x   2  &lt;user&gt;     &lt;owner&gt;          64  8月 18 15:45 /mnt/databox1</span><br><span class="line">3458764513820542749      1 drwxr-xr-x   2  &lt;user&gt;     &lt;owner&gt;          64  8月 18 15:45 /mnt/databox1/&lt;containername&gt;</span><br><span class="line">3458764513820542750      1 drwxr-xr-x   2  &lt;user&gt;     &lt;owner&gt;          64  8月 18 15:45 /mnt/databox1/&lt;containername&gt;/databox1</span><br><span class="line">3458764513820542746      1 drwxrwxr-x   2  &lt;user&gt;     &lt;owner&gt;          64  8月 18 15:46 /mnt/databox2</span><br><span class="line">3458764513820542749      1 drwxr-xr-x   2  &lt;user&gt;     &lt;owner&gt;          64  8月 18 15:46 /mnt/databox2/&lt;containername&gt;</span><br><span class="line">3458764513820542750      1 drwxr-xr-x   2  &lt;user&gt;     &lt;owner&gt;          64  8月 18 15:46 /mnt/databox2/&lt;containername&gt;/databox2</span><br></pre></td></tr></table></figure>

<p>今回のように既存のコンテナーにデータをインポートする要件がある場合は、<code>\\&lt;DeviceIPAddress#1&gt;\&lt;storageaccountname_BlockBlob&gt;</code> 配下に同様の名前のディレクトリを作成する必要があります。ここでディレクトリ名に誤字があると、Azureへのインポート時にまったく新しい別のコンテナーが生成されてしまうので注意が必要です。</p>
<p>以上でディレクトリ作成が完了したので、次はディレクトリの動作確認をしていきます。</p>
<h3 id="ディレクトリの動作確認">ディレクトリの動作確認</h3><p>本手順では、作成したディレクトリ配下でディレクトリとファイルの作成（ディレクトリへの書き込み）ができるかを確認します。</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line"><span class="built_in">touch</span> /mnt/databox1/&lt;containername&gt;/databox1/test.txt</span><br><span class="line"><span class="built_in">ls</span> -l /mnt/databox1/&lt;containername&gt;/databox1</span><br><span class="line"><span class="built_in">rm</span> /mnt/databox1/&lt;containername&gt;/databox1/test.txt</span><br><span class="line"><span class="built_in">ls</span> -l /mnt/databox1/&lt;containername&gt;/databox1</span><br><span class="line"></span><br><span class="line"><span class="built_in">touch</span> /mnt/databox2/&lt;containername&gt;/databox2/test.txt</span><br><span class="line"><span class="built_in">ls</span> -l /mnt/databox2/&lt;containername&gt;/databox2</span><br><span class="line"><span class="built_in">rm</span> /mnt/databox2/&lt;containername&gt;/databox2/test.txt</span><br><span class="line"><span class="built_in">ls</span> -l /mnt/databox2/&lt;containername&gt;/databox2</span><br></pre></td></tr></table></figure>

<p>以上のコマンドが正常に実行されれば、データコピー作業の準備は以上です。<br>ついに、データコピー作業へと移ります。</p>
<h2 id="データコピー">データコピー</h2><img src="/images/2022/20221108a/ワークフロー_(5).JPG" alt="ワークフロー_(5).JPG" width="1200" height="178" loading="lazy">

<h3 id="コピーコマンド実行">コピーコマンド実行</h3><p>今回の案件では<code>cp -prf</code>コマンドでデータコピーを実施しました。</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line"><span class="built_in">cp</span> -prf /&lt;転送元ファイルパス&gt; /mnt/databox1/&lt;containername&gt;/databox1/&lt;転送先パス&gt;</span><br><span class="line"><span class="built_in">cp</span> -prf /&lt;転送元ファイルパス&gt; /mnt/databox2/&lt;containername&gt;/databox2/&lt;転送先パス&gt;</span><br></pre></td></tr></table></figure>

<h3 id="コピーのパフォーマンス">コピーのパフォーマンス</h3><p>ファイルサイズやファイル数に左右されますが、今回の転送速度は100~170MB&#x2F;秒でした。</p>
<p>有効容量の80TBいっぱいにコピーしたい場合、24時間休まずシリアル実行すると、8日前後で完了する計算です。</p>
<p>今回はシリアル実行でしたが、コピー完了までに1台あたり8~9日かかりました。<br>Docs:Data Boxの制限には10セッションまで同時接続できるとあるので…</p>
<blockquote>
<p>Data Box では、NFS 共有上で最大 10 のクライアント接続が同時にサポートされます。</p>
</blockquote>
<p>パラレルでコピーすることによって、さらに転送速度の向上を狙えるようです。</p>
<h2 id="発送">発送</h2><img src="/images/2022/20221108a/ワークフロー_(6).JPG" alt="ワークフロー_(6).JPG" width="1200" height="179" loading="lazy">

<h3 id="デバイスの発送準備処理（チェックサム計算）">デバイスの発送準備処理（チェックサム計算）</h3><p>データコピーが完了したら、デバイスの発送準備処理を実行していきます。<br>ダッシュボードで[Prepare to ship]ページを選択し、[Start preparation]を押下します。</p>
<img src="/images/2022/20221108a/【1号機】発送準備.jpg" alt="【1号機】発送準備.jpg" width="1200" height="574" loading="lazy">

<p>発送準備処理では、キャプチャにある通り、デバイスのロックや転送済みデータの整合性確認、ファイル一覧の作成などが実行されます。</p>
<p>処理完了後には以下のように全項目にチェックがつき、Completedの文字が表示されます。<br><img src="/images/2022/20221108a/発送準備完了_1号機.JPG" alt="発送準備完了_1号機.JPG" width="1200" height="540" loading="lazy"></p>
<p>余談にはなりますが、発送準備処理のリードタイムについても説明しようと思います。<br>Docs:Azure Data Box の発送準備では最遅で数日間かかるとあるので、ここで少し驚く方もいるかと思います。</p>
<blockquote>
<p>チェックサムの計算は、データのサイズによっては数時間から数日間かかる場合があります。</p>
</blockquote>
<p>本当に数日間かかるとすると、発送準備処理だけのためにData Boxサービス料を払うことになり、あまり嬉しくはありません。<br>しかし、いざ発送準備処理を実行してみると、2台平均の所要時間は10分ほどで、見込みよりも大幅に短い時間で完了できました。</p>
<p>今回はData Box1台あたり実効容量の9割近く（70&#x2F;80TB）を使用していたため、最悪のパフォーマンスが考えられる環境でしたが、十数分で完了しました。</p>
<p>発送準備処理のリードタイムは、扱うデータ構造やファイル数、ファイルあたりのサイズなど環境要因に左右されるため参考程度ではありますが、今回の実績ベースでは概ね十数分～数時間程度と考えて良さそうです。<br>ドキュメントにあるリードタイムの目安を鵜呑みにする必要はそれほどなく、より余裕を持ったコピー計画を立ても問題ないと感じています。</p>
<h3 id="Data-Boxシャットダウンと抜線">Data Boxシャットダウンと抜線</h3><p>クローズ処理が完了したら、いよいよ発送に向けて準備をします。<br>Web UIにアクセスしデバイスをシャットダウンしていきます。[Shut down or restart]ページから[Shut down]を押下します。</p>
<img src="/images/2022/20221108a/【1号機】シャットダウンと再起動.jpg" alt="【1号機】シャットダウンと再起動.jpg" width="1200" height="576" loading="lazy">

<p>シャットダウンすると、当たり前ですがファイル共有は使えなくなります。<br>必要に応じて周知しましょう。</p>
<p>押下後に数分あけ、ブラウザの新しいタブを開き再度Web UIにアクセスをします。<br>この時アクセスがタイムアウトすれば、Data Box側のNICがアクティブでない（＝デバイスの電源が落ちた）と判断できます。</p>
<p>次にNWスイッチに接続しているケーブルを抜線し、Data Boxをアンラック・梱包します。</p>
<h3 id="梱包">梱包</h3><p>データボックスを元々の段ボールに梱包し、発送の準備をします。<br>Docs:機能と仕様にある通り、Microsoft社からは（1）Data Box本体と（2）電源ケーブルの2点をレンタルしているので、<br>以上が間違いなく梱包されていることを確認し、段ボールの封をします。</p>
<h3 id="引き渡し">引き渡し</h3><p>発送（Azureデータセンターへの引き渡し）の目処がたった時点で、受け取り時と同様にadbops@microsoft.com宛に引き渡し日時の調整メールを送付します。<br>引き渡しでは以下フォーマットでメールを送付します。</p>
<p>Company name (会社名):<br>Contact name (引き渡し担当者名):<br>Contact tel. no. (引き渡し担当者電話番号):<br>Date of dropoff (引き渡し日):<br>Date of birth (担当者生年月日):<br>Nationality (担当者国籍):<br>Time of dropoff (引き渡し時刻):<br>Car number plate (自動車登録番号):</p>
<p>引き渡し日時が確定しData Boxの発送準備処理が終わるとAzure Portalで認証コードが発行されます。<br>また、azure-noreply@microsoft.comから受取準備が完了した旨のメール（以下、参照）が送付されます。<br><img src="/images/2022/20221108a/引き渡し準備完了メール.JPG" alt="引き渡し準備完了メール.JPG" width="512" height="561" loading="lazy"></p>
<p>あとは引き渡し当日に以下3点を準備してData BoxをAzureデータセンターに引き渡します。</p>
<ol>
<li>認証コード</li>
<li>引き渡し準備完了メールのコピー</li>
<li>引き渡し担当者の写真つき身分証明書</li>
</ol>
<h2 id="Azureへのインポート">Azureへのインポート</h2><img src="/images/2022/20221108a/ワークフロー_(7).JPG" alt="ワークフロー_(7).JPG" width="1200" height="180" loading="lazy">

<h3 id="インポートを待つ">インポートを待つ</h3><p>引き渡し後は特にすることはなく、Azureへのインポートを待ちます。</p>
<p>今回のインポート（デバイス引き渡し完了→BLOBへのインポートまで）のリードタイムは、2台ともに約24時間で、予想よりも短納期で対応していただけた印象です。金曜日にData BoxがAzureデータセンターに到着し、土曜日にインポートが完了したのですが、営業日は考慮せずに対応してもらえるようでした。</p>
<p>Data Boxのワークフローについては以上になります。最後に、全体を通してつまずいたポイントを紹介します。</p>
<h3 id="つまずいたポイント">つまずいたポイント</h3><h4 id="Azureにインポートしたらファイル権限はなくなるのに、一生懸命権限を保持しようとした">Azureにインポートしたらファイル権限はなくなるのに、一生懸命権限を保持しようとした</h4><p>Azureにデータをインポートしてしまえばファイルの権限はなくなってしまうのですが、転送時に権限の保持をしようとしたために、余計な苦労をしました。</p>
<p>当初はNFSでData Boxのファイルシステムをマウントを予定していました。<br>先述のようにデータコピーでは<code>cp -prf</code>コマンドを実行したのですが、NFSマウントの環境下ではコピーコマンド実行時に権限の保持ができませんでした。</p>
<figure class="highlight sh"><table><tr><td class="code"><pre><span class="line">$ <span class="built_in">cp</span> -prf /tmp/databox_dev/test.txt /mnt/databox1/&lt;containername&gt;/databox1</span><br><span class="line"><span class="built_in">cp</span>: <span class="string">&#x27;/mnt/databox1/&lt;containername&gt;/databox1/test.txt&#x27;</span> の所有者の保護に失敗しました: 許可がありません</span><br></pre></td></tr></table></figure>

<p>コピーは成功しており目先の問題はないのですが、エラーメッセージが出るのは気になります。</p>
<p>Data BoxはWindows系OSで動いていると推測し、NFSでのマウントはユーザー名のマッピングにおいて相性が悪いと仮定しました。そこでNFSからCIFSでのマウントに切り替えところ、権限を保持したままコピーできるようになったのですが、Azureの世界ではファイルの権限は引き継がれません。</p>
<p>振り返るとファイルの権限を保持するオプションも、それを保持するための苦労も必要なかったと今は思います。</p>
<p>ファイルの権限を保持することに意味はなく、不具合を引き起こす場合もあるので、コピー時には余計なオプションを付け足すのは避けたほうがよいでしょう。</p>
<h2 id="まとめ">まとめ</h2><p>以上、秋のブログ週間の一貫で、Data Boxを使ってみてわかった詳細なワークフロー・手順やつまずいたポイントを紹介してきました。</p>
<p>AzureのData Boxが日本で提供され始めたのは2019年ごろなので、比較的若いサービスです。</p>
<p>第三者のレポートが非常に少なく、検討段階では情報収集に苦労しました。</p>
<p>本記事がData Box利用を検討される方の参考になれば幸いです。</p>
<p>データ移行にかけられる期間と回線費用を考えると、数十TB規模のデータを1-2週間で移行できるのは非常に有効な手段だと思います。</p>
]]></content>
    <summary type="html">オンプレからクラウドへのデータ移行に関して、AzureのData Boxというサービスを利用する機会があったので、詳細なワークフローや失敗談について共有します。昨今のDX推進の流れにのり、システムのクラウドシフト/リフトに取り組む方も多いかと思います。「クラウドへの移行を考えているがデータ量が膨大で移行ができない」といった悩みがあったり...</summary>
    <category term="Cloud" scheme="https://future-architect.github.io/categories/Cloud/"/>
    <category term="Azure" scheme="https://future-architect.github.io/tags/Azure/"/>
    <category term="クラウドマイグレーション" scheme="https://future-architect.github.io/tags/%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%83%9E%E3%82%A4%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3/"/>
    <category term="データ移行" scheme="https://future-architect.github.io/tags/%E3%83%87%E3%83%BC%E3%82%BF%E7%A7%BB%E8%A1%8C/"/>
  </entry>
</feed>
