1. 今回の投稿について こんにちは、サイオステクノロジーの安藤 浩です。SIOS Tech Labアドベントカレンダー10日目の投稿です。 技術よりというよりマネジメントよりの内容で投稿します。私は開発も行いますが、プロジェクト管理を担当することがあり、プロジェクト管理で気を付けたいポイントを記載してみます。 ソフトウェア開発のプロジェクトでは、適切なプロジェクト管理が欠かせません。スケジュール、コスト、リスク、コミュニケーション、スコープ管理など様々な考慮をする必要があります。 特にWBS(Work Breakdown Structure)の作成はプロジェクト全体像の工数、タスクを把握するために重要な基盤です。 今回は、WBSの作成方法、スケジュール作成、JiraやNotionの比較をご紹介します。 2. WBS(Work Breakdown Structure)とは WBSはプロジェクトのタスクを階層的に分解し、管理可能な単位に整理する手法です。プロジェクトの成果物やタスクを「見える化」することで、以下のメリットが得られます: タスクの漏れ防止 :全体を分解することで、見落としがちなタスクを発見 正確な工数見積もり :小さな単位に分解することで精度向上 進捗管理の容易化 :各タスクの完了状況を明確に把握 責任の明確化 :誰が何を担当するかを明示(出来る限りタスクに対して1名のみを推奨) 3. WBS作成の基本ステップ 3.1. 成果物の洗い出し プロジェクトで作成すべき成果物を最初に洗い出します。 成果物の例 : 要件定義書 基本設計書 詳細設計書 ソースコード 単体テスト仕様書兼成績書 結合テスト仕様書兼成績書 リリース手順書 マニュアル・ドキュメント 3.2. タスクの分解 成果物の洗い出しと並行して、進めてもよいですが、成果物に対して必要なタスクを詳細に分解します。 分解の原則 : 1タスクは1~5人日程度の粒度にする → タスクが大きすぎると漏れや管理が困難になります。 具体的なタスクの完了条件を明確にする。→ タスクによっては完了条件を決めることが難しい場合がありますが、タスクの完了条件を決めることで対応内容を明確にします。 「○○の作成」「○○のレビュー」など動詞で終わる形にする。 → タスク名から何をするタスクか判別できるようにします。 担当者を1名で対応できるタスクに分割します。 → 複数担当者にわたる場合は、タスク分割が必要です。 WBS構造の例 : 担当やプロジェクト、会社によって異なると思いますが、3階層くらいまでにすることがWBS構造の把握をするためのポイントかと思います。 あまりに階層が深すぎたり、階層が浅すぎると工程やタスクがわかりにくくなります。 1. 要件定義フェーズ 1.1 要件ヒアリング 1.1.1 ヒアリングシート作成 1.1.2 ユーザーヒアリング実施 1.1.3 要件整理 1.2 要件定義書作成 1.2.1 機能要件定義 1.2.2 非機能要件定義 1.2.3 レビュー・承認 2. 設計フェーズ 2.1 基本設計 2.1.1 システム構成設計 2.1.2 画面設計 2.1.3 DB設計 2.2 詳細設計 ... 3.3. タスクの前後関係(依存関係)の定義 タスク間の依存関係を明確にすることで、どのタスクが完了していなければ着手できないのかの明確化や正確なスケジュール作成を行うことができます。 依存関係の種類 : プロジェクト管理 依存関係 を見ると 「PMBOKでは依存関係という用語は定義されていない」とあり、PMBOKでは依存関係という定義がないことを知りましたが、タスクの依存関係を意識するとスケジュールが立てやすいです。 種類 説明 例 FS(Finish to Start) 先行タスク完了後に後続タスク開始 設計完了後に実装開始 SS(Start to Start) 先行タスク開始と同時に後続タスク開始 設計書作成とレビュー準備を同時開始 FF(Finish to Finish) 先行タスク完了と同時に後続タスク完了 テスト実施とテスト報告書作成が同時完了 SF(Start to Finish) 先行タスク開始時に後続タスク完了 新システム稼働開始時に旧システム停止 依存関係の定義例 : 以下タスクがざっくりしていますが、こんな感じです。 タスクA(要件定義)→ タスクB(基本設計)[FS] タスクB(基本設計)→ タスクC(詳細設計)[FS] タスクC(詳細設計)→ タスクD(実装)[FS] タスクD(実装)→ タスクE(単体テスト)[FS] 3.4. タスクのバッファ設定 技術的に不確実性を抱えることは通常ですが、リスクに備えて各タスクにバッファ(余裕時間)を設定したり、各タスクではバッファを考慮せずに、全体の工数に対してバッファを積むことがあります。 ここでのタスクのバッファは工数見積もり時に考慮するもので、スケジュール上のバッファとは区別します。 タスクバッファの指針 : 各タスクに例: 5~20%の余裕を持たせる(プロジェクトによってどのくらいかも異なります。バッファを積まずに楽観的な工数とする場合もあります) 不確実性が高いタスクほど多めにバッファを確保 経験の浅いメンバーが担当するタスクは余裕を持たせる 例:実装タスクの工数見積もり ├── 機能A実装: 2人日 + バッファ0.5人日 = 2.5人日 ├── 機能B実装: 3人日 + バッファ0.5人日 = 3.5人日 └── 機能C実装: 4人日 + バッファ1人日 = 5人日 4. スケジュールの作成 WBSで洗い出したタスクをもとに、具体的なスケジュールを作成します。 月から金まであって「よし、5日だから5人日のタスクができるな!」となって失敗するケースがありますが、考慮すべき要素はいくつかあります。 スケジュール作成で考慮すべき要素 営業日(土日祝日、長期休暇など) スキル・経験 タスク優先度 バッファ 前工程、後工程の状況 稼働率 など 4.1. 稼働日を考慮したスケジュール作成 少なくとも営業日(稼働日)はどの会社にもあると思うので、スケジュールに織り込むことは必須です。 また、有休や稼働率の考慮なども必要なので、考慮すべき要素は以下かと思います。 考慮すべき要素 : 項目 内容 土日祝日 カレンダー上の休日を除外 年末年始・お盆 会社の休業期間 有給取得予定 メンバーの休暇予定 他プロジェクトとの兼務 稼働率の考慮(50%稼働など) 会議・定例 開発タスク以外の時間 スケジュール作成の際に毎回営業日いつだったか確認してSpreadsheet で営業日外(休日・祝日)一覧を書き出すのが面倒なので、直近やった方法を紹介しておきます。 前提 前提として、WBSには各工程のタスクの分割が行われ、タスクに対して工数が振られているとします。 No 工程 タスク 工数(人日) 1 設計 基本設計書作成 3 2 設計 詳細設計書作成 5 3 実装 機能A実装 2.5 4 実装 機能B実装 3.5 5 実装 機能C実装 5 6 テスト 単体テスト 3 7 テスト 結合テスト 4 手順 営業日の情報を入手する。YYYY-MM-dd の形式で一覧でスプレッドシート上で扱いやすければよいですが、カレンダー形式になっていたり、画像やPDFの場合があるので、 1の画像やPDFをGemini 3 Proに読み込ませて「祝日と休日すべてをYYYY-MM-dd の形式で一覧に出力して」とプロンプトを入力します。※弊社には有休奨励日が設定されている(休日と休日の間の営業日が多い)ので念のためその日は休む人がいそうなので考慮に入れておきます。 以下のような感じで出力してくれました。 **12月 (11日間)** 2025-12-06 2025-12-07 2025-12-13 2025-12-14 2025-12-20 2025-12-21 2025-12-27 2025-12-28 2025-12-29 2025-12-30 2025-12-31 ざっとあっていそうか確認してスプレッドシートに「休日」のシートを作成します。 3の結果を張り付けます。WBSの工数や納期によっていつまでの期間の情報が必要か異なります。 例えば2025/12/01がプロジェクト開始だとして、以下のようにC2のセルの開始日を「 =WORKDAY(WBS!F1 - 1, 1, '休日'!$B$4:$B$140) 」のようにすると休日でを避けて開始日を設定することができます。 7. D2セルの終了日は「 =WORKDAY(C2-1,E2+F2,'休日'!$B$4:$B$140) 」のようにして開始日からE2: 対応工数+F2: スケジュールバッファの期間での休日を除いた終了日が設定されます。 ※スケジュールバッファは以下で検討。 8. プロジェクトメンバーが複数いて並列対応が可能であれば、「並列対応」の列を用意してタスクを並列で進める考慮も行います。 9. 2026年1月中旬に終わりそうだとなります。 細かい作業ですが、休日一覧文字認識やフォーマットを変更したりするなども手間なので生成AIを活用して楽になりました。 4.2. スケジュールバッファの設定 プロジェクト全体やフェーズ単位で、期間的なバッファを設定します。タスクのバッファとは異なり、スケジュール上の調整日として確保します。結合テストの期間やリスクが見込まれるマイルストーンでは期間的なバッファを持たせることで例えばリリースに間に合わないということがないようにします。 スケジュールバッファの指針(例) : プロジェクトバッファ :全体期間の10~15%をプロジェクト終盤に確保(プロジェクトによってどのくらいかも異なります) マイルストーンバッファ :フェーズ終了時に調整日を設定 例:実装フェーズのスケジュール ├── 機能A実装: 1/6 ~ 1/14(6営業日) ├── 機能B実装: 1/15 ~ 1/18(4営業日) ├── 機能C実装: 1/19 ~ 1/25(5営業日) └── フェーズバッファ: 1/26 ~ 1/28(2営業日) ----------------------------------- 合計: 17営業日 4.3. ガントチャートによる可視化 ガントチャートは、作成したスケジュールを視覚的に表現するツールですが、Excel やスプレッドシートで書くと色づけするなど変更に耐えられないので、Backlog, Jira, Notion などのツールを使った方が良いと思います。 ガントチャートに含める情報 : タスク名 担当者 開始日・終了日 進捗率 見積工数(人日) 依存関係(矢印で表示) マイルストーン など ガントチャート作成ツールの例 : Microsoft Project Jira(タイムラインビュー) Notion(タイムラインビュー) Backlog プロジェクトメンバー全員で共通認識が容易にできることが重要だと思うので、Microsoft Projectはライセンスが高かったり、プロジェクトメンバー全員がMicrosoft Projectをもっていないとファイルが開けなかったりと導入には注意が必要です。 5. Jira と Notion の比較 直近だとJira(無料版) と Notionを利用しましたが、小~中規模ではNotionのほうが操作性が良く学習コストが低いと思いました。 Notionはやや操作が重くなることがありましたが、ステータスの変更によって進捗率の算出など数式を利用したいときはJiraの無料枠ではAutomation の月の上限がすぐに達してしまうのでうまくいきませんでした。 今回でだいぶJiraになれたので、次回機会があれば有料版も利用したいところです。 観点 Jira Notion 価格 有料(無料枠あり) 無料プランあり 得意な領域 アジャイル開発 ドキュメント管理、柔軟な運用 学習コスト やや高い 比較的低い カスタマイズ性 設定項目が豊富 自由度が非常に高い 開発ツール連携 GitHub, Bitbucket等と連携 API経由 チーム規模 中~大規模 小~中規模 WBSやガントチャートをJiraやNotionに落とし込む方法も記載しようと思いましたが、時間がないので次回にしたいと思います。 6. まとめ 本記事では、プロジェクト管理の基本であるWBS作成からスケジュール作成のポイント、Jira・Notionの比較についてご紹介しました。 1. WBS作成について : 成果物を洗い出し、タスクを適切な粒度(1〜5人日)に分解する タスクの依存関係を明確にする 不確実性に備えてタスクバッファを設定する 2. スケジュール作成について : 営業日(土日祝日、有給、稼働率)を正確に考慮する プロジェクト全体やフェーズ単位でスケジュールバッファを確保する ガントチャートで可視化し、進捗管理を容易にする 3. ツール選定について : Jiraはソフトウェア開発・アジャイルに強く、大規模チーム向け Notionは柔軟性が高く、ドキュメント管理も一元化したい小〜中規模チーム向け 7. 参考リンク プロジェクトマネジメント知識体系ガイド(PMBOK) プロジェクトマネジメント プロジェクト管理 依存関係 Jira公式ドキュメント Notion公式ドキュメント ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post プロジェクト管理入門 – WBS・スケジュール作成 first appeared on SIOS Tech Lab .
「SIOS社員が今年一年で学んだこと」アドベントカレンダー9日目です。 最近少し苦戦した、Kongの小ネタを紹介させていただきます。 想定状況 旧サービスから新サービスに移行するにあたって、まずは一部のユーザーにのみ公開し動作を確認してから全体公開したい…という状況を考えます。 旧サービス: http://httpbin.org/xml 新サービス: http://httpbin.org/json こういった作業を本番で作業を行う場合はdecKコマンドを叩くと思いますが、今回は分かりやすさ重視でKong Manager上からポチポチ設定していく手順を紹介します。 また、canary release pluginはenterprise onlyのため、順当な手段で試そうとするとハードルが高いです。幸い Kong academy 内で実際のKongの操作を試せるvirtual labではenterprise onlyなpluginでも使うことができるので、そちらを使わせていただきましょう。 操作手順 workspace作成 適当なworkspaceを作ります。複数のworkspace作成もenterprise機能だった気が… serviceの作成 Gateway Servicesから、旧サービスとなるhttp://httpbin.org/xmlを割り当てたcanary-api-serviceを作成します。 Name: canary-api-service Full URL: http://httpbin.org/xml routeの作成 上記のserviceに紐づいたrouteを作成します。 Name: canary-api-route Service: canary-api-service Path: /api/canary 疎通確認 curl -i http://localhost:8000/api/canary HTTP/1.1 200 OK Content-Type: application/xml Content-Length: 522 Connection: keep-alive Date: Sat, 06 Dec 2025 11:55:35 GMT Server: gunicorn/19.9.0 Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true X-Kong-Upstream-Status: 200 X-Kong-Upstream-Latency: 2009 X-Kong-Proxy-Latency: 2 Via: 1.1 kong/3.10.0.6-enterprise-edition <?xml version='1.0' encoding='us-ascii'?> <!-- A SAMPLE set of slides --> <slideshow title="Sample Slide Show" date="Date of publication" author="Yours Truly" > <!-- TITLE SLIDE --> <slide type="all"> <title>Wake up to WonderWidgets!</title> </slide> <!-- OVERVIEW --> <slide type="all"> <title>Overview</title> <item>Why <em>WonderWidgets</em> are great</item> <item/> <item>Who <em>buys</em> WonderWidgets</item> </slide> </slideshow> key auth pluginを設定 routeに対してpluginを適応します。 Scoped Route: canary-api-route consumerを作成 旧サービスを見せるか新サービスを見せるか分類するため、2つのconsumerを作成します。 Username: general-consumer 同様に、Username: vip-consumerでvip-consumerを作成します。 key auth credential付与 それぞれのconsumerにcredentialを付与します。 general-consumerはgeneral-apiを割り当てます 同様に、vip-consumerにはvip-apiを割り当てます。 疎通確認 apikeyがない場合、401で弾かれます。 curl -i http://localhost:8000/api/canary HTTP/1.1 401 Unauthorized Date: Thu, 06 Nov 2025 02:13:07 GMT Content-Type: application/json; charset=utf-8 Connection: keep-alive WWW-Authenticate: Key realm="kong" Content-Length: 96 X-Kong-Response-Latency: 5 Server: kong/3.4.3.21-enterprise-edition { "message":"No API key found in request", "request_id":"e9f5080d632bba08e2ba023597c3d006" } 先ほど設定したapikeyがあれば、アクセスが可能です。 curl -i http://localhost:8000/api/canary?apikey=general-api curl -i http://localhost:8000/api/canary?apikey=vip-api HTTP/1.1 200 OK (以下略) acl pluginを設定 Scoped Route: canary-api-route Allow: general-acl, vip-acl acl credentialを付与 各consumerにacl credentialを付与します vip-consumerに対しても同様に、vip-aclを設定します。 canary pluginを設定 以下の通り設定します。 Scoped Route: canary-api-route UpstreamHost : httpbin.org UpstreamPort : 80 UpstreamUri : /json Groups : vip-acl Hash: allow 疎通確認 これで、general-consumerは旧サービス(/xml)が見え、vip-consumerは新サービス(/json)が見えるようになりました。 curl -i http://localhost:8000/api/canary?apikey=general-api HTTP/1.1 200 OK Content-Type: application/xml Content-Length: 522 Connection: keep-alive Date: Sat, 06 Dec 2025 11:55:35 GMT Server: gunicorn/19.9.0 Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true X-Kong-Upstream-Status: 200 X-Kong-Upstream-Latency: 2009 X-Kong-Proxy-Latency: 2 Via: 1.1 kong/3.10.0.6-enterprise-edition <?xml version='1.0' encoding='us-ascii'?> <!-- A SAMPLE set of slides --> <slideshow title="Sample Slide Show" date="Date of publication" author="Yours Truly" > <!-- TITLE SLIDE --> <slide type="all"> <title>Wake up to WonderWidgets!</title> </slide> <!-- OVERVIEW --> <slide type="all"> <title>Overview</title> <item>Why <em>WonderWidgets</em> are great</item> <item/> <item>Who <em>buys</em> WonderWidgets</item> </slide> </slideshow> curl -i http://localhost:8000/api/canary?apikey=vip-api HTTP/1.1 200 OK Content-Type: application/json Content-Length: 429 Connection: keep-alive Date: Sat, 06 Dec 2025 12:02:41 GMT Server: gunicorn/19.9.0 Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true X-Kong-Upstream-Status: 200 X-Kong-Upstream-Latency: 1530 X-Kong-Proxy-Latency: 3 Via: 1.1 kong/3.10.0.6-enterprise-edition { "slideshow": { "author": "Yours Truly", "date": "date of publication", "slides": [ { "title": "Wake up to WonderWidgets!", "type": "all" }, { "items": [ "Why <em>WonderWidgets</em> are great", "Who <em>buys</em> WonderWidgets" ], "title": "Overview", "type": "all" } ], "title": "Sample Slide Show" } } 本リリース vip-consumerに対してカナリアリリースを行い、十分に動作検証ができたとします。canary release状態から通常リリースに変更するには、serviceに登録しているendpointを新サービスのものに変更し、canary release pluginを削除すればOKです いかがでしたか? 長々とした拙筆にお付き合いいただきありがとうございました。本記事が皆様の、何かしらの助けになれば幸いです。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【Kong初心者向け】Canary Release Pluginの使い方 first appeared on SIOS Tech Lab .
はじめに 前回はダウンタイムを最小限に抑えるBlue/Greenデプロイ戦略について紹介しました。これは旧環境(Blue)と新環境(Green)を完全に分離して用意し、外部からのトラフィックを一瞬でGreenに切り替える手法です。これにより、ダウンタイムを抑制しつつバージョンアップを完了させ、かつ問題発生時の切り戻し(ロールバック)も瞬時に行えるという、安全性の高い方法です。 本記事では、安全なバージョンアップに不可欠なバックアップの必要性と、その際に直面するデータ管理の課題について深堀して解説します。 なぜKubernetesのリソースバックアップが必要なのか バージョンアップ中の操作ミスやエラーにより、Kubernetesでは以下の二つの要素が失われる可能性があります。 クラスターリソースの設計図:Deployment、Serviceなどクラスター全体を構成する設定情報 アプリケーションデータ:データベースに保存されたアプリケーションデータなど サービスを元の状態に完全に復元するには、アプリケーションデータに加え、クラスターの設計図も完全に復元できる状態が必要です。 ステートレスとステートフルアプリケーションの違い デプロイメント戦略を考えるうえで、データの有無が大きな違いとなります。 ステートレス:データを持たず、リソースの入れ替えが容易です。バージョンアップ時にデータ移行の問題は発生しません。 ステートフル:永続的なデータ(例:DBのデータ)を保持し、その状態に依存して動作します。データの損失を防ぎつつ、新旧バージョン間でデータの互換性をどう担保するかが大きな壁となります。 Kubernetesのデータ構成要素 Kubernetesが「データ」をどのように管理しているか、バックアップとリストアに必要な要素を解説します。 etcd Kubernetesクラスターの全てのメタデータと状態を保持しています。 etcdのバックアップこそがクラスターの設計図のバックアップであり、これがなければPodやServiceの定義は全て失われてしまいます。etcdのバックアップは最も重要です。 PV、PVC(アプリケーションの永続データの実体) PVC(Persistent Volume Claim): アプリケーションが「ストレージを使いたい」と要求するリソース定義です。 PV(Persistent Volume): 実際のストレージ(ディスクなど)の実体です。 アプリケーションデータを復元するには、PVの実データだけでなく、そのデータを使うためのPVCというKubernetesリソース定義もセットでリストアしなければなりません。この「リソースとデータの実体をまとめて管理する」点が、従来のバックアップとの大きな違いです。 Blue/Greenにおけるデータ移行の課題 ステートフルなアプリケーションの安全なバージョンアップにおいて、バックアップ・リストアが課題になる箇所を説明します。 課題1:ロールバック時のデータ損失 Blue/GreenデプロイでデータをコピーしてGreen環境を構築した場合、ロールバックでBlue環境に戻ると、Green環境で発生した新規データは全て失われます。 技術的には「コピーした時点に戻す」という期待通りの動作ですが、これはデータ損失を意味します。 最も問題なのは、ロールバック後に改めてバージョンアップを試みる際、失われたデータは二度と取り戻せないという点です。 安全なロールバックを実現するには、このデータ損失を防ぎつつ、リソースとデータを同時に、任意の時点に復元する必要があります。 課題2:新旧バージョンのデータ互換性 Blue/Greenデプロイでデータストアを共有した場合、新バージョン(Green)がDBスキーマを変更すると、即座に旧バージョン(Blue)のアプリケーションが動かなくなります。 バックアップツールは「データの互換性」そのものを解決できません。データ移行処理(DBマイグレーション)を、デプロイプロセスの中に組み込む必要があり、この統合が複雑になります。 安全なバージョンアップを実現するには、これらの課題を解消するために、リソースとデータを同時に扱える専門的なツールが必要になります。 まとめ 今回の記事では、Kuberntesのバックアップは、etcdとPV/PVCの二軸で、セットで行うことが重要であることを解説しました。しかし、ステートフルなアプリケーションのバージョンアップでは、データの互換性と整合性が課題となります。 これらの複雑な課題を解消し、安全なリソースとデータのバックアップ・リストアを実現するにはKubernetes専門のバックアップツールが不可欠です。次回は、そのソリューションである「Velero」について解説します。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 初めてのKubernetesバージョンアップ:Kubernetesにおけるバックアップの必要性とデータ管理の課題 first appeared on SIOS Tech Lab .
はじめに 皆さん、こんにちは!PS-SLの織田です。 SIOS Tech Labアドベントカレンダー8日目になります!今回は、『 Java言語で学ぶデザインパターン入門 』の第1章を読んだ感想をまとめていきたいと思います。購入してからそこそこ時間が経ってしまったのですが、なんとか第1章を読むことができたので内容をまとめていきたいと思います。 Iteratorパターンとは 第1章ではIteratorパターンに関する内容が記されていました。Iteratorパターンとは何かしらの集合があったときに、それらを順に指していき 処理を繰り返し実行 することです。文字で説明しても何のこっちゃという感じなので、具体的なコードとともに説明していきます。 基本要素:Book.java public class Book { private String name; public Book(String name) { this.name = name; } public String getName() { return name; } } このクラスは単純なデータホルダーです。本の名前を保持するprivateフィールドと、それを取得するgetName()メソッドを提供します。コレクションに格納される個々の要素を表現する役割を担います。Iteratorパターンにおいては「要素」の役割を果たし、パターン全体の基盤となるシンプルなクラスです。 集約オブジェクト:BookShelf.java import java.util.Iterator; public class BookShelf implements Iterable<Book> { private Book[] books; private int last = 0; public BookShelf(int maxsize) { this.books = new Book[maxsize]; } public Book getBookAt(int index) { return books[index]; } public void appendBook(Book book) { this.books[last] = book; last++; } public int getLength() { return last; } @Override public Iterator<Book> iterator() { return new BookShelfIterator(this); } } 本棚を表現するクラスで、Iteratorパターンの中核となる「集約」の役割を担います。内部では固定サイズの配列を使って本を管理し、本の追加(appendBook)、指定位置の本の取得(getBookAt)、現在の本の数を取得(getLength)といった基本機能を提供します。 反復子:BookShelfIterator.java import java.util.Iterator; import java.util.NoSuchElementException; public class BookShelfIterator implements Iterator<Book> { private BookShelf bookShelf; private int index; public BookShelfIterator(BookShelf bookShelf) { this.bookShelf = bookShelf; this.index = 0; } @Override public boolean hasNext() { if (index < bookShelf.getLength()) { return true; } else { return false; } } @Override public Book next() { if (!hasNext()) { throw new NoSuchElementException(); } Book book = bookShelf.getBookAt(index); index++; return book; } } 実際の反復処理を担当するクラスです。BookShelfへの参照と現在の位置を示すindexフィールドを持ち、hasNext()で次の要素の存在を判定し、next()で要素を順次返します。 このクラスの重要な点は、BookShelfの内部構造を知らずに反復処理を行えることです。getLength()とgetBookAt()メソッドを通じてのみBookShelfにアクセスし、直接配列を操作することはありません。 利用例:Main.java import java.util.Iterator; public class Main { public static void main(String[] args) { BookShelf bookShelf = new BookShelf(4); bookShelf.appendBook(new Book("Around the World in 80 Days")); bookShelf.appendBook(new Book("Bible")); bookShelf.appendBook(new Book("Cinderella")); bookShelf.appendBook(new Book("Daddy-Long-Legs")); // 明示的にIteratorを使う方法 Iterator<Book> it = bookShelf.iterator(); while (it.hasNext()) { Book book = it.next(); System.out.println(book.getName()); } System.out.println(); // 拡張for文を使う方法 for (Book book: bookShelf) { System.out.println(book.getName()); } System.out.println(); } } Iteratorパターンの使用方法を実演するクライアントクラスです。BookShelfインスタンスを作成し、複数の本を追加した後、二つの異なる方法で反復処理を行います。 一つ目は明示的にiterator()メソッドを呼び出してIteratorを取得し、while文でhasNext()とnext()を使った伝統的な方法です。二つ目はJava 5以降で導入された拡張for文を使った方法で、Iterableインターフェースの実装により自動的に内部でIteratorが使用されます。 いずれにしても繰り返し処理の中ではIteratorのメソッドのみ呼び出されています。ここは伏線なので覚えておいてください。 Iteratorパターンで嬉しいこと 一見すると、冗長な書き方に見えるかもしれませんが、このパターンを使うことで受けられる恩恵があります。例えば、現在のBookShelfクラスは配列で管理をしているため、最初に指定した本棚の大きさ以上のデータは入れられません。そこで、配列ではなくjava.util.ArrayListを使うよう修正するとします。こうなると、「複数のファイルにまたがって修正を実施しなきゃいけないのか…」と思うかもしれませんが、実はBookShelfクラスだけ修正すれば大丈夫です。 BookShelf.java(修正後) import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class BookShelf implements Iterable<Book> { private List<Book> books; public BookShelf(int initialsize) { this.books = new ArrayList<>(initialsize); } public Book getBookAt(int index) { return books.get(index); } public void appendBook(Book book) { books.add(book); } public int getLength() { return books.size(); } @Override public Iterator<Book> iterator() { return new BookShelfIterator(this); } } 先述の通り、Mainの繰り返し処理の中ではIteratorのメソッドのみ呼び出されています。つまりBookShelfクラスに依存していないため修正も不要ということです。 もしiteratorパターンを使っていない状況で、配列からjava.util.Listへの修正を行った場合、main関数の繰り返し処理は以下のように変更する必要があります。 Main.java(配列版) public class Main { public static void main(String[] args) { BookShelf bookShelf = new BookShelf(4); bookShelf.appendBook(new Book("本A")); bookShelf.appendBook(new Book("本B")); // 配列を取得して処理 Book[] books = bookShelf.getBooks(); for (int i = 0; i < bookShelf.getLength(); i++) { System.out.println(books[i].getName()); } } } Main.java(List版) import java.util.List; public class Main { public static void main(String[] args) { BookShelf bookShelf = new BookShelf(4); bookShelf.appendBook(new Book("本A")); bookShelf.appendBook(new Book("本B")); // Listを取得して処理 List<Book> books = bookShelf.getBooks(); // Book[]からList<Book>に変更 for (int i = 0; i < books.size(); i++) { // getLength()からsize()に変更 System.out.println(books.get(i).getName()); // books[i]からget(i)に変更 } } } 上記のコードの通りMain.javaで複数箇所の修正が必要になり、手間がかかるだけでなく、コンパイルエラーが発生する可能性もあります。 import文の追加 変数型の変更 メソッド呼び出しの変更 まとめ 第1章を読んだ感想としては、「デザインパターンを意識しなくてもコード を書くのはなんとかなりそう。ただ、可読性や保守性はめっちゃ低いなぁ」という感じでした。例えるなら、きれいに整えられた回路(下図①)と、ただ闇雲にジャンク品を使いながら無計画に作られた回路(下図②)のような具合です。デザインパターンを理解していなくても動くものは作れるでしょう。しかし、作りたいものが複雑になればなるほど、デザインパターンなしでは保守・運用の難易度が跳ね上がります。まだまだ読み始めたばかりですが、今後もデザインパターンを学び、保守・運用のしやすいコードを実際の業務でも書けるように頑張りたいと思います。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post デザインパターンのすゝめ ~Iteratorパターン編~ first appeared on SIOS Tech Lab .
こんにちは、伊藤です。 この記事は、アドベントカレンダー7日目の記事になります。 今回は、Exchange Onlineで、メールの自動転送を制限する方法を紹介します。 Exchange Onlineでは特定のユーザー・グループ・ドメインに対して自動転送可能なメールドメインを制限することが可能です。 今回はその中でも 特定のドメインメールのユーザーに対してメール自動転送を不可にする方法 、 特定のドメインメールのユーザーに対してメール自動転送可能ドメインを制限する方法 を紹介します。 メールの自動転送を制限する目的 メールの自動転送を制限する主な目的は、メールに含まれる情報の外部漏洩を軽減することです。メールでは、ファイルやパスワードのやり取りを行うことがありますが、自動転送を制限しない場合、全てのドメインのメール宛てに転送可能になるため、情報漏洩のリスクが高まります。 設定に必要なMicrosoft Entra IDのロールについて 今回紹介する設定を行うためには、「Exchange管理者」、「セキュリティ管理者」ロールを持つMicrosoft Entra IDのアカウントが必要です。 特定のドメインメールのユーザーに対してメール自動転送を不可にする 例として検証ドメイン(soito001.mail.onmicrosoft.com)のユーザに対してメール自動転送を不可にします。 アウトバウンド スパム フィルター ポリシーの設定 1. Microsoft 365 Defender ポータル(https://security.microsoft.com/)に管理者アカウントでサインインします。 2. [メールとコラボレーション] > [ポリシーとルール] > [脅威ポリシー] > [スパム対策] の順に選択します。 3. [スパム対策ポリシー] ページで、メール自動転送を制限したいドメイン(例:soito001.mail.onmicrosoft.com) 専用のカスタムポリシーを作成します。[+ ポリシーの作成] > [Outbound] の順に選択します。 4. ポリシーの名前を設定します(例: soito001.mail.onmicrosoft.com Auto-forward Policy)。 5. [ユーザー、グループ、およびドメイン] で、このポリシーを適用する対象として、[ドメイン] に”soito001.mail.onmicrosoft.com”を指定します。特定のユーザー、グループに対して適用したい場合は、それぞれ[ユーザー] 、[グループ]で指定してください。 6. [送信の保護設定]で、[自動転送ルール] に「オフ – 転送が無効になっています」を設定します。 7. 確認画面にて適用するポリシーを確認し、[作成]を選択します。 自動転送の制限を確認する 1. テストアカウント(exchangetest001@soito001.mail.onmicrosoft.com)の自動転送を有効にして、テストアカウントにメールを送信します。 2. Exchange 管理センター (EAC)(https://admin.exchange.microsoft.com/)に管理者アカウントでサインインします。 3. [メールフロー] > [メッセージ追跡] > [+ 追跡を開始] の順に選択します。 4. [新しいメッセージ追跡]で、[受信者]にテストアカウントを設定して[検索]を選択します。時間の範囲等の条件で絞り込むことも可能です。 5. テストアカウントへのメール送信に該当する追跡結果を確認し、[メッセージイベント]で外部転送がブロックされている内容を確認します。 特定のドメインメールのユーザに対してメール自動転送可能ドメインを制限する 例として検証ドメイン(soito001.mail.onmicrosoft.com)のユーザに対して社内ドメインのみへのメール自動転送を許可します。 アウトバウンド スパム フィルター ポリシーの設定 1. Microsoft 365 Defender ポータル(https://security.microsoft.com/)に管理者アカウントでサインインします。 2. [メールとコラボレーション] > [ポリシーとルール] > [脅威ポリシー] > [スパム対策] の順に選択します。 3. [スパム対策ポリシー] ページで、メール自動転送を制限したいドメイン(例:soito001.mail.onmicrosoft.com) 専用のカスタムポリシーを作成します。[+ ポリシーの作成] > [Outbound] の順に選択します。 4. ポリシーの名前を設定します(例: soito001.mail.onmicrosoft.com Auto-forward Policy)。 5. [ユーザー、グループ、およびドメイン] で、このポリシーを適用する対象として、[ドメイン] に”soito001.mail.onmicrosoft.com”を指定します。特定のユーザー、グループに対して適用したい場合は、それぞれ[ユーザー] 、[グループ]で指定してください。 6. [送信の保護設定]で、[自動転送ルール] に「オン – 転送が有効になっています」を設定します。 7. 確認画面にて適用するポリシーを確認し、[作成]を選択します。 リモートドメインの設定 1. Exchange 管理センター (EAC)(https://admin.exchange.microsoft.com/)に管理者アカウントでサインインします。 2. [メール フロー] > [リモート ドメイン] の順に選択します。 3. ここで、許可するドメイン と 既定(その他すべて) の設定を行います。 A. 許可する外部ドメインの設定 [+ リモート ドメインを追加] をクリックします。 [ドメイン名を指定]で、[リモートドメイン]に社内ドメインを入力します。 [メールの返信の種類] で、「自動転送を許可する」 (Allow automatic forwarding) を有効にします。 確認画面にて適用するリモートドメインの設定を確認し、[保存]を選択します。 B. 既定ドメインの設定 (許可されていないその他すべてのドメイン) リモート ドメインの一覧から、「Default」または * (アスタリスク) という名前の既定のリモート ドメインを見つけ、[返信の種類を編集]を選択します。 「自動転送を許可する」 (Allow automatic forwarding) を無効にして保存します。 自動転送の制限を確認する 1. テストアカウント(exchangetest001@soito001.mail.onmicrosoft.com)の自動転送を有効にして、[メールの転送先]に社内ドメインのメールアドレスを指定し、テストアカウントにメールを送信します。 2. 社内ドメインのメールアドレスへの転送は許可されているため、社内ドメインのメールアドレスで転送メールを受信することができます。 3. Exchange 管理センター (EAC)(https://admin.exchange.microsoft.com/)のメッセージ追跡機能にて、テストアカウントへのメール送信に該当する追跡結果を確認し、[メッセージイベント]で外部転送が完了した内容を確認します。 4. テストアカウント(exchangetest001@soito001.mail.onmicrosoft.com)の[メールの転送先]に社内ドメイン以外のメールアドレスを指定し、テストアカウントにメールを送信します。 5. Exchange 管理センター (EAC)(https://admin.exchange.microsoft.com/)のメッセージ追跡機能にて、テストアカウントへのメール送信に該当する追跡結果を確認し、[メッセージイベント]で外部転送がブロックされている内容を確認します。 特定のドメインメールのユーザーに対してメール自動転送を不可にする方法 で確認したメッセージの内容とは異なりますが、イベント: Dropはメールの配送がここで 破棄(Drop) されたことを示しており、”handled AutoForward addressed to external recipient”は、外部受信者宛の自動転送(AutoForward)として処理されたことを示しております。外部への自動転送の設定で禁止されているからここで破棄するという挙動になります。 まとめ 今回は、Exchange Onlineで、 特定のドメインメールのユーザーに対してメール自動転送を不可にする方法 、および 特定のドメインメールのユーザーに対してメール自動転送可能ドメインを制限する方法 を紹介しました。 Exchange Onlineの設定の参考にしていただければ幸いです。 参考 参考 Microsoft 365 での外部メール転送の構成と制御 – Microsoft Defender for Office 365 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Exchange Onlineのメール自動転送を制限する first appeared on SIOS Tech Lab .
アドベントカレンダー6日目の記事です。 今回はClaude Codeを使っていて「毎回同じ説明をするのが面倒」「プロジェクト固有のルールを覚えさせたい」という問題を解決する方法を紹介します。 また今回Web開発に使えそうな汎用Skillsのテンプレートを作成し、Githubで公開しましたのでぜひ本記事を読む際に参考にしていただき、よりよいスキルセットがあればPRお待ちしています。 https://github.com/atomic-kanta-sasaki/claude-code-general-skills/tree/main/.claude/skills Skillsとは何か? Skillsは、Claudeに特定のタスクの実行方法を教えるためのナレッジパッケージです。 公式ドキュメントでは以下のように説明されています: Skillsはフォルダ内の指示、スクリプト、リソースで、Claudeが特定のタスクを繰り返し実行する方法を教えます。 簡単に言えば、 新しいチームメンバーに渡すオンボーディング資料 のようなものです。プロジェクトの規約、ツールの使い方、ワークフローを文書化しておけば、Claudeがそれを参照して作業してくれます。 Skillsの特徴 自動呼び出し : ユーザーが明示的に指定しなくても、タスクに応じてClaudeが自動で適切なスキルを選択 プログレッシブ・ディスクロージャー : 必要な情報だけを段階的に読み込むため、コンテキストを圧迫しない コード実行可能 : 指示だけでなく、Pythonスクリプトなども含められる Skillsとサブエージェント・CLAUDE.mdの違い Claude Codeには似たような機能がいくつかあります。違いを整理しておきましょう。 機能 目的 トリガー コンテキスト Skills 知識・手順の提供 自動(description基準) メインと共有 Subagents タスクの委任・並列処理 自動/手動 独立 CLAUDE.md プロジェクト全体のコンテキスト 常時読み込み メインと共有 Commands 定型プロンプト実行 手動(/command) メインと共有 使い分けの指針 Skills : 特定タスク(レビュー、テスト作成など)の専門知識 Subagents : 独立したコンテキストで並列作業させたい場合 CLAUDE.md : プロジェクト全体で常に参照すべき情報 Commands : よく使うプロンプトのショートカット Skillsのディレクトリ構造 Skillsは以下の場所に配置します: .claude/skills/ └── your-skill-name/ ├── SKILL.md # 必須:メインの指示ファイル ├── reference.md # 任意:参照ドキュメント ├── examples.md # 任意:使用例 ├── scripts/ # 任意:ヘルパースクリプト │ └── helper.py └── templates/ # 任意:テンプレートファイル └── template.txt 配置場所による違い 場所 スコープ ~/.claude/skills/ 全プロジェクトで使用可能(個人用) .claude/skills/ プロジェクト固有(チーム共有可能) SKILL.md の書き方 基本構造 --- name: your-skill-name description: | このスキルが何をするか、いつ使うべきかの説明。 具体的なトリガーワードや使用シーンを含める。 version: 1.0.0 --- # Your Skill Name ## Overview このスキルの概要説明 ## Instructions ステップバイステップの指示 ## Examples 具体的な使用例 フィールドの説明 フィールド 必須 制限 説明 name 64文字、小文字・数字・ハイフンのみ スキルの識別子 description 1024文字 最重要 : いつ呼び出すかの判断基準 version 任意 – バージョン管理用 descriptionの書き方(最重要ポイント) Skillsが正しく呼び出されるかどうかは、 descriptionの書き方で9割決まります 。 Claudeはdescriptionを見て「このスキルを使うべきか」を判断するため、曖昧な記述では呼び出されません。 悪い例 description: コードを手伝う これでは「いつ」「何を」手伝うのかわかりません。 良い例 description: | Pythonコードのセキュリティレビューを実施。 OWASP Top 10に基づく脆弱性チェック、認証・認可の検証、入力バリデーション確認。 セキュリティチェック、脆弱性診断、コードのセキュリティ評価時に使用。 良いdescriptionのポイント: 具体的な動作 : 何をするスキルか明確に トリガーワード : どんな言葉で呼び出されるべきか 使用シーン : どんな状況で使うか 境界線 : 何に使わないか(オプション) Skillsの呼び出しの仕組み プログレッシブ・ディスクロージャー Skillsは段階的に情報を読み込む設計になっています: 1. 起動時 └─ 全スキルの name と description だけを読み込み 2. ユーザーリクエスト受信 └─ description を参照してマッチするスキルを判断 3. スキル選択時 └─ SKILL.md の本文を読み込み 4. 必要に応じて └─ scripts/ や references/ を読み込み この設計により、多数のスキルをインストールしても、実際に使うスキルの情報だけがコンテキストを消費します。 スクリプトの活用 Skillsの強力な機能の1つが、 Pythonスクリプトの実行 です。 指示だけでは不確実な処理(フォーマット、バリデーションなど)をスクリプトで確実に実行できます。 例:フォーマッタースキル --- name: python-formatter description: | Pythonコードをプロジェクト標準にフォーマット。 Black, isort, ruffを適用。Pythonファイルの整形時に使用。 version: 1.0.0 --- # Python Formatter ## Workflow ### Step 1: フォーマット実行 Run: `python .claude/skills/python-formatter/scripts/format.py <file>` ### Step 2: 結果確認 フォーマット結果を確認し、問題があれば報告。 # scripts/format.py import subprocess import sys def main(): file = sys.argv[1] subprocess.run(["black", file]) subprocess.run(["isort", file]) print(f" Formatted: {file}") if __name__ == "__main__": main() スクリプトのメリット 確実性 : LLMの揺らぎなく、決まった処理を実行 コンテキスト節約 : スクリプトの内容ではなく、出力だけがトークンを消費 再利用性 : 同じスクリプトを複数のスキルで共有可能 Skillsが有効なケース・有効でないケース 有効なケース 定型的なレビュー作業 : セキュリティチェック、コード品質チェック ドキュメント生成 : API仕様書、README、ADRなど フォーマット・バリデーション : スクリプトと組み合わせて確実に実行 プロジェクト固有のルール適用 : ブランドガイドライン、コーディング規約 有効でないケース 創造的なタスク : アイデア出し、自由な設計 対話的な作業 : フィードバックを受けながら進める作業 コンテキスト依存の判断 : プロジェクト全体を俯瞰した判断 単純な質問応答 : スキルを使うまでもないタスク ベストプラクティス 1. スキルはフォーカスを絞る 1つのスキルに複数の機能を詰め込まず、目的別に分割しましょう。 ❌ code-helper(何でもやる) ✅ security-review(セキュリティ特化) ✅ test-generator(テスト生成特化) ✅ api-design(API設計特化) 2. SKILL.mdは500行以下に 長すぎるスキルはコンテキストを圧迫します。詳細は別ファイルに分割し、SKILL.mdはメニューとして機能させましょう。 3. 具体例を含める Claudeが「成功とは何か」を理解できるよう、入出力の例を含めましょう。 4. 制限事項を明記する スキルができないことを明示すると、誤用を防げます。 セキュリティ上の注意 Skillsは強力な機能ですが、注意点もあります: 信頼できるソースのみ使用 : 自作またはAnthropicの公式スキルを推奨 APIキーをハードコードしない : 環境変数を使用 ダウンロードしたスキルは監査 : 実行前にスクリプトの内容を確認 まとめ Claude Code Skillsは、AIコーディングを「汎用アシスタント」から「プロジェクト専門家」に進化させる機能です。 ポイントをまとめると: descriptionが命 : 適切に書かないと呼び出されない 段階的読み込み : 多数のスキルを入れてもパフォーマンスに影響しにくい スクリプト活用 : 確実に実行したい処理はコード化 フォーカスを絞る : 1スキル1目的で設計 まずはシンプルなスキルから始めて、徐々に拡張していくのがおすすめです。 次の記事では、Web開発で使い回せる汎用スキル集を紹介します。 この記事はClaude Code公式ドキュメントおよび実際の検証に基づいて作成しています。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Claude Code Skillsの使い方と汎用テンプレート公開 first appeared on SIOS Tech Lab .
こんにちは、PS-SLの織田です。SIOS Tech Labアドベントカレンダー5日目になります。 今回のブログは資格取得に関するものになります。今年の7月に Azure Administrator Associate(AZ-104) に合格しました。この試験は、Azureの広範な知識と実践的な理解が求められるため、闇雲に学習を進めてもなかなか成果が出にくいものです。 私が実際に行った学習方法の中で特に効果的だった方法と、これから受験される方への具体的なアドバイスを、私の失敗談も交えながら、詳しくご紹介します。 最も合格に直結した学習リソース 私の学習において、最も合格に直結し、知識の定着に役立ったのはUdemyで提供されている高品質な予想問題集でした。学習を始めた当初は、「試験問題はAzureリソースのことをよく理解してから解いたほうが良いかな…」と考えていたのですが、むしろこの問題集を中心に学習を進めた方がよいと後になって気づきました。 本番さながらのシミュレーション : 予想問題集は、実際の試験と同じように、複数の選択肢、ドラッグアンドドロップ、ケーススタディなど、多様な問題形式で構成されています。時間を計って模擬試験として取り組むことで、 2時間の制限時間内に問題を解ききるペース配分 を身につけることができました。 出題傾向の把握と知識の定着 : 実際に本番と非常に似た、あるいは全く同じトピックの問題が出題されることが多々あります。これにより、試験で問われる核となる概念や、細かい設定項目についての理解が深まります。 正解の選択肢だけでなく、不正解の選択肢がなぜ間違っているのか を理解することで、知識をより確固たるものにすることができました。実際に本番では、練習問題とほぼ同じ問題が多数出題されました。練習問題をやりこむことで大きく加点を増やすことができ合格率を高めることができます。 本番環境を意識したMSLearn活用 AZ-104試験の最大の特徴は、試験中に公式ドキュメントであるMS Learnを参照することが許可されている点です。自分は高校や大学の試験のように「全てを暗記する」必要があると勘違いしていたのですが、実は「調べる力」も求められる試験でした。 MSLearnで「調べる力」を鍛える : 合格の鍵は、「どのトピックについて問われているか」を瞬時に判断し、「MS Learnのどのページを見れば確実な情報が得られるか」の当たりをつける能力です。最初のうちは欲しいページを探すのに時間がかかってしまいますが、繰り返し行っていくうちに素早く欲しいページを見つけられるようになります。 練習中からMS Learnを確認する習慣 : 予想問題集を解く際も、最初から「MS Learnを見ても良い」という本番ルールを適用し、常に「この問題はMS Learnのどのページを見れば解決できるか」という視点で検索する癖をつけましょう。 ドキュメント構造に慣れる : 練習を通じて、各Azureサービス(例:Virtual Machines、VNet、Storage Account)の概要ページ、料金ページ、具体的なデプロイ手順やトラブルシューティングに関するドキュメントが、MS Learnのどこに、どのようなキーワードで存在しているか、おおよその「あたり」を頭の中に作り上げておくことが、本番での貴重な時間短縮につながります。 Azure Storage アカウントの種類をまとめた表。このような同一サービスにおける種類・プランによる差異を比較できるページにあたりをつけておくと試験本番で重宝する。 私の失敗談:モチベーションの回復から推奨学習サイクルへ 実は、私の学習の初期段階では大きな失敗がありました。 最初は自分の実力を測ろうと、MS Learnを全く見ずに予想問題集に挑戦しました。結果は散々で、ほとんどの問題が分からず、スコアも非常に低く、 「こんなに難しいのか」とモチベーションが一気に低下 してしまいました。 しかし、合格した方からのアドバイスや冷静に試験の特性を考え直した結果、学習方法を根本的に変更しました。 推奨する効率的な学習サイクル 私が最も効果的だと思った学習サイクルは以下の通りです。 MS Learnを参照しながら練習問題を解く : 最初は正解率を気にせず、「どのドキュメントが使えるか」を探しながら解きます。問題を解くための手がかりを検索する能力を養うことに集中します。 間違った問題・自信のない問題の徹底的な深掘り(深掘り学習) : 単に正解の解説を読むだけでなく、間違えた理由や、偶然正解したものの自信がないトピックについては、徹底的に時間をかけて深く理解します。 「深掘り学習」の具体的なアプローチ 深掘りとは、単なる知識の丸暗記ではなく、その知識を多角的に理解し、本番で応用できる状態にすることです。 多角的な情報の整理 : 表や図の活用 : 例えば、ストレージアカウントの異なる冗長オプション(LRS, GRS, ZRS, GZRS)の特性や、VMの異なるサイズ(SKU)の機能や価格の違いなど、 比較が必要な情報を自分なりに表や図に整理 します。 実践的な比較 : 似た機能を持つAzureリソース(例:Azure FirewallとNetwork Security Group)について、それぞれの ユースケース、メリット・デメリット を対比して整理します。 公式ドキュメントとの紐づけ : 「この問題はMS Learnのどのドキュメントに該当する内容か」を再確認し、 いつでもそのページにすぐにたどり着けるように、キーワードや目次構造を脳内にインデックス化 します。 特に、PowerShellやAzure CLIのコマンド例が問われる問題については、MS Learnで実際のコマンドを確認し、なぜその引数が必要なのかを理解します。 実際に私が作成した冗長オプションをまとめた図。文字だけでは分かりずらい内容も図表にすることで視覚的に理解することができる。 まとめ 実は今回初めてテストセンターを利用して少し緊張していましたが、問題集をやりこんだおかげで、落ち着いていつも通り回答することができたと思います。練習問題をやりこんでおいてよかったです。 ただし、今回ご紹介した方法はあくまで一例ですので、参考程度に見てもらえればと思います。実際に学習を進める過程でご自身に合った学習方法で進めていくと良いかなという感じです。皆さんの学習が効率的に進むことを願っています! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post AZ-104 合格体験記:効果的な学習法と予想問題集の活用戦略 first appeared on SIOS Tech Lab .
はじめに こんにちは!サイオステクノロジーの吉永です。 この記事は「 SIOS社員が今年一年で学んだこと 」のアドベントカレンダー4日目の記事です。今年は生成AI活用事業やWEBアプリケーション開発に携わる中で、AIコーディングアシスタントとの協業について多くのことを学びました。今回は試行錯誤を重ねる中で、今年になって流行りだした「仕様駆動開発(SDD)」と実現するためのツールについて書こうと思います。 先日、OSC福岡2025で「もうAIに振り回されない!OpenSpecで実現する予測可能なAI開発」というテーマで登壇する機会もいただき、この一年の学びを整理することができました。本記事では、その内容をより詳しくお伝えしたいと思います。 さて、AIコーディングアシスタント(Claude Code、GitHub Copilot、Cursorなど)を使っていると、こんな経験はありませんか? 「ユーザー認証機能を追加して」と頼んだら、1000行のコードが生成された 「いや、JWTじゃなくてセッション認証で…」と訂正したら、また1000行のコードが生成された 「そもそもReactじゃなくてNext.jsで…」と再度訂正したら、さらに1000行のコード生成… この無限ループ地獄、実は「Vibeコーディング」と呼ばれる現象なんです。 Vibeコーディングとは何か 「Vibeコーディング」という言葉は、OpenAIの共同創業者であるAndrej Karpathyが2025年2月に初めて提唱した概念です。LLM(大規模言語モデル)の性能が飛躍的に向上したことで可能になった、全く新しい開発スタイルを指します。 There's a new kind of coding I call "vibe coding", where you fully give in to the vibes, embrace exponentials, and forget that the code even exists. It's possible because the LLMs (e.g. Cursor Composer w Sonnet) are getting too good. Also I just talk to Composer with SuperWhisper… — Andrej Karpathy (@karpathy) February 2, 2025 Vibeコーディングの特徴 Vibeコーディングは、従来のソフトウェア開発の常識を覆すような特徴を持っています。まず、 コードの存在を忘れて感覚的に開発する という点が挙げられます。開発者はコードの詳細を理解することなく、AIに自然言語で指示を出すだけで機能が実装されていきます。 エラーメッセージが表示されても、その意味を理解しようとはせず、 コメントなしでそのままコピペ してAIに投げます。AIが何らかの修正を提案してくれることを期待するわけです。 さらに驚くべきことに、 コードが開発者の理解を超えて成長 していきます。気づいたら数千行のコードベースになっていて、その全貌を誰も把握していないという状況が生まれます。音声入力でAIに指示を出すことも一般的で、散歩しながらコーディングすることも可能です。 バグに遭遇した場合は、修正できなければ回避策で対処するか、 ランダムな変更を加えてバグが消えるまで試す というアプローチが取られます。これは従来のデバッグとは全く異なる手法です。 一見すると非常に効率的で革新的に見えますが、実はこのアプローチには深刻な問題が潜んでいます。 根本的な4つの問題 Vibeコーディングの背後には、以下の4つの根本的な問題が存在します。 曖昧な要求仕様 最も大きな問題は、「何を作るか」が明確でないことです。開発者が曖昧な指示をすると、AIは自身の学習データに基づいて推測で補完します。例えば「ユーザー認証を追加して」と言った場合、AIはJWT認証、セッション認証、OAuth、Basic認証など、様々な選択肢の中から独自に判断して実装を進めます。 結果として、開発者が意図していた認証方式とは全く異なる実装が生成されることになります。これを修正するために再度プロンプトを投げると、また別の実装が生成される…という無限ループに陥るのです。 コンテキストの欠如 プロジェクトには必ず技術スタック、コーディング規約、アーキテクチャパターンといった プロジェクト固有のコンテキスト が存在します。しかし、これらの情報がAIに伝わっていないと、既存のコードベースに適合しないコードが生成されてしまいます。 例えば、プロジェクトがNext.js 15のApp Routerを使っているのに、AIがPages Routerで実装してしまう。データベースアクセスにPrismaを使っているのに、生SQLで書かれてしまう。このような不整合が頻発します。 非決定的な出力 LLMの性質上、同じプロンプトでも毎回違う結果が返ってきます。これは 再現性の欠如 を意味します。昨日うまくいった方法が今日は通用しない。同僚が成功した方法を自分が試しても同じ結果にならない。このような状況では、チーム開発が非常に困難になります。 知識の散逸 AIとの対話の中で重要な決定事項が決まっていきます。「このAPIはRESTfulに設計する」「認証トークンはHTTP-onlyクッキーに保存する」「エラーハンドリングは専用のミドルウェアで行う」など、プロジェクトの重要な方針が決まっていくわけです。 しかし、これらの 決定事項はチャット履歴に埋もれてしまい 、後から見返すことができません。新しいセッションを始めたり、別の開発者が作業を引き継いだりすると、同じ議論を最初からやり直すことになります。 これらの問題を解決するため、コミュニティでは様々なアプローチが試みられてきました。 Vibeコーディングの問題を解決するため、最初に登場したのが CLAUDE.md というアプローチです。 CLAUDE.mdの登場 CLAUDE.mdは、プロジェクトのルートディレクトリに配置する AIへの指示書 です。Anthropic社のClaude Codeに特化しており、プロジェクトのガイドライン、ベストプラクティス、制約事項などを記述します。 従来のアプローチ:CLAUDE.md/AGENTS.md これにより、先ほど述べた「コンテキストの欠如」という問題を解決しようとしました。AIがプロジェクトの技術スタック、コーディング規約、アーキテクチャパターンを理解できるようになるわけです。 # プロジェクト概要 ECサイトのバックエンド開発 ## 技術スタック - Node.js + TypeScript - Express.js、PostgreSQL、Jest ## コーディング規約 - 関数は単一責任の原則に従う - エラーハンドリングは必須 - テストファーストで実装 ## 実装時の注意 1. TypeScriptの型定義を含める 2. APIはRESTfulに設計 3. 認証はJWT Bearer tokenを使用 CLAUDE.mdは2025年6月頃から段階的に進化してきました。 CLAUDE.mdの進化 第1段階(2025年6月頃) では、単なる チートシート として使われていました。プロジェクトの基本情報を提供し、よく使うコマンドをリスト化する程度の内容でした。この段階では、開発者がマニュアルを見る手間を省く程度の効果しかありませんでした。 第2段階(2025年7月〜9月) になると、 AIの制約を定義 するツールへと進化しました。詳細なスタイルガイドを記述し、ワークフローを自動化する指示を含めるようになりました。さらに、過去の失敗から学習するため、「やってはいけないこと」のリストも追加されました。 モノレポ(複数のプロジェクトを1つのリポジトリで管理する構成)に対応するため、階層的な設定管理も可能になりました。ルートのCLAUDE.mdで全体的なルールを定義し、各サブプロジェクトのCLAUDE.mdで個別のルールを上書きできるようになったのです。 AGENTS.mdの登場 2025年8月19日、OpenAIが AGENTS.md をオープンフォーマットとして公開しました。これは、Anthropic社独自のCLAUDE.mdをより汎用的にしたものです。 AGENTS.mdの最大の特徴は、 複数のAIツール間で共有される共通指示 として機能することです。Claude Code、GitHub Copilot、Cursor、Windsurf、Aiderなど、様々なAIコーディングアシスタントで同じ指示書を使い回せます。 また、 推奨言語は英語 です。これには明確な理由があります。AIモデルの学習データは英語が圧倒的に多く、技術用語も英語の方が曖昧性が少ないためです。国際的なチームで開発する場合も、英語で書かれていれば誰でも理解できます。 AGENTS.mdには、以下のような内容が含まれます: 実装ガイドライン として、コード規約(命名規則、ファイル構成、型定義)、エラーハンドリングパターン、セキュリティチェックリスト、認証実装パターンなどを記述します。 ワークフロー指示 として、新機能開発プロセス(要件確認→実装→検証→コミット)、バグ修正プロセス、コードレビュー基準などを定義します。 これにより、AIは単にコードを生成するだけでなく、プロジェクトのワークフローに沿った作業を進められるようになりました。 CLAUDE.md/AGENTS.mdの限界 しかし、CLAUDE.md/AGENTS.mdにも限界があることが分かってきました。特に、プロジェクトが成長するにつれて以下の問題が顕在化してきたのです。 仕様の管理が困難 プロジェクト全体の説明が1つのファイルに含まれているため、様々な問題が発生します。 まず、 すべての機能の仕様が混在 してしまいます。認証機能、決済機能、通知機能、管理画面…といった個別の機能の仕様が、すべて1つのファイルに書かれることになります。ファイルが肥大化し、数千行になることも珍しくありません。 次に、 過去の決定事項がどこかに埋もれて しまいます。「3ヶ月前に決めた認証方式の詳細はどこに書いてあったっけ?」と探しても、膨大なファイルの中から該当箇所を見つけるのは困難です。 また、 現在作業中の内容が見つけにくい という問題もあります。複数の機能を並行して開発している場合、どれが完了していて、どれが進行中で、どれが未着手なのか、ファイルを読むだけでは判断できません。 さらに深刻なのは、 途中参加メンバーが全体像を把握することが困難 という点です。新しく参画したエンジニアが数千行のCLAUDE.md/AGENTS.mdを読んでも、プロジェクトの歴史的経緯や現在の状態を理解するのは非常に難しいのです。 変更の追跡が不可能 CLAUDE.md/AGENTS.mdはGitで管理されているため、理論上は変更履歴を追跡できます。しかし実際には、 どの機能がいつ追加されたかを把握するのは困難 です。 ファイル全体の差分を見ても、「500行目に3行追加、800行目に5行修正」といった情報しか得られません。それが認証機能の変更なのか、決済機能の追加なのか、コーディング規約の更新なのか、差分だけでは判断できないのです。 仕様変更の履歴が残らない ことも問題です。「なぜ認証方式をJWTからセッション認証に変更したのか?」という意思決定の背景が記録されていないため、同じ議論が何度も繰り返されることになります。 複数人で作業している場合、この問題はさらに深刻です。メンバーAが認証機能の仕様を更新し、同時にメンバーBが決済機能の仕様を追加すると、Gitのコンフリクトが発生します。1つのファイルに全てが集約されているため、 並行作業が非常に困難 なのです。 さらに、 セッションが異なると情報が共有されない という問題もあります。Claude Codeで月曜日に作業した内容が、火曜日の新しいセッションでは引き継がれません。CLAUDE.mdに書かれていない暗黙的な決定事項は、毎回失われてしまうのです。 スケーラビリティの欠如 最も深刻なのは、 プロジェクトが大きくなると管理不能になる ことです。 小規模なプロジェクト(1〜2人、数ヶ月の開発期間)であれば、CLAUDE.md/AGENTS.mdは十分機能します。しかし、10人以上のチーム、1年以上の開発期間となると、話は別です。 特に、既存機能の変更(1→N)が困難です。新しい機能を0から作る場合(0→1)は、CLAUDE.md/AGENTS.mdに新しいセクションを追加すればよいだけです。しかし、既存の機能を変更する場合(1→N)、ファイル内の該当箇所を見つけ、整合性を保ちながら更新する必要があります。 大規模プロジェクトでは、各フォルダにCLAUDE.md/AGENTS.mdが点在することもあります。frontend/CLAUDE.md、backend/CLAUDE.md、infra/CLAUDE.mdといった具合です。これらのファイル間で矛盾が生じると、AIはどちらを優先すべきか判断できず、混乱してしまいます。 結果として、 全体像の把握が困難 になります。プロジェクトの現在の状態を理解するには、複数のCLAUDE.md/AGENTS.mdをすべて読み、Gitの履歴を追跡し、さらにコードベースを確認する必要があります。 これらの限界を克服するため、新しいアプローチが求められました。それが 仕様駆動開発(SDD) です。 仕様駆動開発(SDD)の台頭 2025年に入って、 仕様駆動開発(Spec-Driven Development、SDD) という新しいアプローチが急速に注目を集めるようになりました。 SDDの本質 SDDの本質は、一言で表すと以下のようになります: 「コードを書く前に、何を作るかをAIと合意する」 これは当たり前のように聞こえるかもしれません。しかし、Vibeコーディングの時代には、この「当たり前」が忘れ去られていたのです。 従来のソフトウェア開発では、要件定義→設計→実装という順序が基本でした。しかし、AIコーディングアシスタントの登場により、「とりあえずAIにコードを書かせてみて、動かなかったら修正する」というアプローチが一般化しました。 SDDは、AIコーディング時代においても、 設計の重要性 を再認識させてくれるアプローチなのです。 SDDのキーコンセプト SDDには、4つのキーコンセプトがあります。 明確な仕様定義 は、曖昧さを排除することを目指します。「ユーザー認証を追加して」ではなく、「Google OAuthを使った認証を追加し、セッションは24時間有効とし、ログアウト機能も提供する」といった具体的な仕様を定義します。 人間とAIの共通理解 は、同じ認識を持つことを重視します。AIが生成するコードが、開発者の意図と完全に一致するよう、事前に仕様をすり合わせます。これにより、「期待と違う」という問題を大幅に減らせます。 予測可能な実装 は、実装前に結果が見えることを意味します。詳細な仕様があれば、実装後のコードがどのようになるか、事前に予測できます。これにより、手戻りを最小限に抑えられます。 追跡可能な変更 は、いつ、何が変わったかを明確にします。仕様の変更履歴を残すことで、「なぜこうなっているのか」という疑問に答えられるようになります。 従来フローとSDDフローの違い この違いを図で表すと、非常に明確です。 従来の Vibeコーディングフロー は、以下のような循環構造になっています: アイデアをプロンプトに変換し、AIがコードを生成します。生成されたコードをデバッグし、問題があれば修正します。しかし、修正してもまた別の問題が発生し、フラストレーションが溜まっていきます。結局、最初に戻って別のアプローチを試す…という無限ループに陥るのです。 一方、 SDDの開発フロー は、直線的で明確です: アイデアを仕様という形で文書化します。その仕様を人間がレビューし、AIと合意します。合意が得られてから初めて実装に移ります。実装が完了したら、仕様をアーカイブして知識として蓄積します。各ステップが明確で、後戻りが最小限に抑えられているのが特徴です。 SDDがもたらす4つの価値 SDDは、開発プロセスに以下の4つの価値をもたらします。 予測可能性 により、実装前に結果が予測できます。詳細な仕様があれば、「この機能を実装すると、データベーススキーマはこうなり、APIエンドポイントはこれだけ追加され、フロントエンドコンポーネントはこう変更される」ということが事前に分かります。これにより、予期しない副作用を防げます。 監査可能性 により、すべての変更が追跡可能です。仕様の変更履歴を見れば、「いつ、誰が、なぜ、この変更を行ったか」が明確に分かります。コンプライアンスやセキュリティ監査においても、この追跡可能性は非常に重要です。 再利用性 により、仕様が知識として蓄積されます。過去のプロジェクトで作成した認証機能の仕様を、新しいプロジェクトで再利用できます。同じ問題を何度も解決する必要がなくなるのです。 チーム協業 により、異なるAIツールでも同じ仕様を共有できます。メンバーAがClaude Codeを使い、メンバーBがCursorを使っていても、同じ仕様を参照していれば、一貫性のあるコードが生成されます。 現在の主要なSDDツール(2025年11月時点) SDDを実現するツールは、2025年に次々と登場しました: Kiro (AWS) – https://kiro.dev Spec Kit (GitHub) – https://github.com/github/spec-kit OpenSpec (Fission AI) – https://github.com/Fission-AI/OpenSpec BMad Method (BMad Code) – https://github.com/bmad-code-org/BMAD-METHOD cc-sdd (国産OSSツール) – https://github.com/gotalab/cc-sdd それぞれのツールには特徴がありますが、今回はOpenSpecを中心にご紹介します。 OpenSpecとは OpenSpecは、Fission AIが開発した仕様駆動開発を実現する軽量なワークフロー管理ツールです。 OpenSpecが解決する問題 OpenSpecは、先ほど述べたCLAUDE.md/AGENTS.mdの限界を、直接的に解決することを目指して設計されています。 既存プロジェクト向けに最適化 されているのが、OpenSpecの最大の特徴です。新規プロジェクトを0から立ち上げる場合ではなく、すでに動いているプロジェクトに後から導入できるよう設計されています。既存のコードベースに影響を与えることなく、段階的に導入できます。 複数のAIツールに対応 しているのも重要なポイントです。Claude Code、Cursor、GitHub Copilot、Aiderなど、様々なAIコーディングアシスタントで使えます。チームメンバーがそれぞれ異なるツールを使っていても、同じ仕様を共有できるのです。 軽量な構造 により、学習コストが低いことも魅力です。複雑な設定ファイルやビルドツールは不要で、基本的にはMarkdownファイルを編集するだけです。既存のドキュメント作成スキルがあれば、すぐに使い始められます。 変更管理の明確化 は、OpenSpecの核心的な機能です。Gitのpull requestのように、仕様の差分を明確に管理できます。「何が追加され、何が変更され、何が削除されたか」が一目で分かります。 OpenSpecワークフロー OpenSpecは、以下の4つのステップで動作します。 Proposal(提案)では、変更内容を提案します。「二要素認証を追加したい」「検索機能にフィルタを追加したい」といった変更を、構造化された形で提案します。この段階では、まだコードは生成されません。 Review(レビュー)では、提案された仕様を確認・調整します。人間が仕様を読み、不明点があればAIと対話しながら詳細化していきます。この段階で、実装の方向性が固まります。 Apply(適用)では、合意された仕様に基づいて実装を実行します。AIが仕様を読み取り、それに従ってコードを生成します。仕様が明確なので、AIの出力も予測可能です。 Archive(アーカイブ)では、完了した変更を知識として蓄積します。提案時に作成した変更差分を、マスター仕様に統合します。これにより、プロジェクトの仕様が常に最新の状態に保たれます。 OpenSpecの核となる概念:2つのフォルダ OpenSpecの構造は、驚くほどシンプルです。基本的に、2つのフォルダで構成されています。 AGENTS.md openspec/ ├── specs/ # 現在の仕様 │ └── auth/ │ └── spec.md # 認証機能の仕様 │ └── changes/ # 提案中の変更 └── add-profile-filters/ | ├── proposal.md # 変更内容 | ├── tasks.md # タスクリスト | ├── design.md # 技術仕様 | └── specs/ | └── auth/ | └── spec.md # 仕様の差分 └── add-frontend-ui/ openspec/specs/ フォルダには、現在の仕様を管理します。これは、プロジェクトの「現在の状態」を表します。認証機能、決済機能、検索機能など、各機能の仕様が独立したファイルとして管理されます。 openspec/changes フォルダには、提案中の変更を管理します。これは、プロジェクトの「未来の状態」を表します。各変更提案は独立したディレクトリとして管理され、その中に提案内容、タスクリスト、技術仕様、仕様の差分などが含まれます。 この構造により、 CLAUDE.md/AGENTS.md の「すべてが1つのファイルに混在する」という問題が解決されます。また、複数の変更を並行して進めることも容易になります。 変更差分の概念 OpenSpecの最も強力な機能の1つが、Gitのpull requestと同様の変更差分管理です。 # プロフィール仕様の変更差分 ## ADDED Requirements ### 要件: ロールフィルター システムはユーザーロールによるフィルタリングを提供しなければならない ## MODIFIED Requirements ### 要件: 検索レスポンス(更新版) 検索結果にはフィルター適用状態を含めなければならない ## REMOVED Requirements ### 要件: 全件表示 (廃止:パフォーマンスの問題により) この差分形式により、レビュー時に何が変わるのかが一目で分かります。 ADDED セクションには、新しく追加される要件が記載されます。この例では、「ロールフィルター」という新機能が追加されることが分かります。 MODIFIED セクションには、既存の要件の変更が記載されます。「検索レスポンス」という既存の要件が更新され、フィルター適用状態を含むようになることが分かります。 REMOVED セクションには、廃止される要件が記載されます。「全件表示」機能がパフォーマンスの問題により廃止されることが分かります。 この差分形式は、Gitのdiffやプルリクエストに慣れているエンジニアにとって、非常に理解しやすいものです。コードレビューと同じように、仕様もレビューできるのです。 OpenSpecの実際の使い方 実際のシナリオを使って、OpenSpecの使い方を詳しく見ていきましょう。 シナリオ:二要素認証(2FA)を追加 既存の認証システムに2FA(二要素認証)を追加する場合を考えます。現在はメールアドレスとパスワードによる認証のみですが、セキュリティ向上のため、SMSまたは認証アプリによる2FAを追加したいとします。 Step 1: 変更提案の作成 まず、変更提案を作成します。コマンドラインから直接実行することも、AIアシスタントに自然言語で依頼することもできます。 # コマンドライン、またはAIアシスタントに依頼 /openspec:proposal 二要素認証を追加 または、より自然な言葉で: 開発者: 「プロフィール検索にロールとチームでのフィルター機能を 追加するOpenSpec変更提案を作成して」 AI: 「OpenSpec変更提案を作成します...」 *openspec/changes/add-profile-filters/を生成* このコマンドを実行すると、AIが自動的に以下のファイル構造を生成します: openspec/changes/add-2fa/ ├── proposal.md # 変更の意図と背景 ├── tasks.md # 実装タスクリスト ├── design.md # 技術仕様 └── specs/auth/ └── spec.md # 2FAの仕様(差分) proposal.md には、なぜこの変更が必要なのか、どのような価値を提供するのかといった背景情報が記載されます。「セキュリティ向上のため、2FAを導入する。これにより、不正アクセスのリスクを大幅に低減できる」といった内容です。 tasks.md には、実装に必要なタスクが列挙されます。「データベーススキーマに2FA用のテーブルを追加」「SMS送信機能を実装」「認証アプリとの連携機能を実装」「フロントエンドに2FA設定画面を追加」といった具体的なタスクです。 design.md には、技術的な設計が記載されます。「2FAのコードは6桁の数字とし、有効期限は5分間」「SMS送信にはTwilio APIを使用」「認証アプリとの連携にはTOTPプロトコルを使用」といった技術的な決定事項です。 specs/auth/spec.md には、認証機能の仕様の差分が記載されます。これが最も重要なファイルで、既存の認証仕様に対する変更点が明確に示されます。 Step 2: 仕様のレビューと調整 生成された仕様を確認し、必要に応じて調整していきます。この段階では、AIと対話しながら仕様を詳細化していきます。 開発者: 「ロールとチームフィルターの受け入れ条件を追加して」 AI: 「仕様差分を更新します…」 specs/profile/spec.mdとtasks.mdを編集 例えば、「2FAのバックアップコードはどうするか?」「2FAの設定は任意か必須か?」「既存ユーザーへの移行はどうするか?」といった疑問点を、この段階でAIと議論します。 AIが提案する仕様に納得できない場合は、何度でも修正を依頼できます。「バックアップコードは10個生成し、1回使用したら無効にする」「既存ユーザーは次回ログイン時に2FA設定を促すが、強制はしない」といった具体的な要件を追加していきます。 この段階では、まだコードは一切生成されていません。 仕様を固めることに集中します。コードを書く前に設計を固めるという、ソフトウェア開発の基本原則に立ち返っているわけです。 Step 3: 実装 仕様に合意したら、いよいよ実装フェーズに移ります。 # コマンドライン、またはAIアシスタントに依頼 /openspec:apply add-profile-filters または、自然言語で: 開発者: 「仕様が良さそうです。実装しましょう」 AI: 「タスクを順番に実装します...」 Task 1.1 ✓ データベーススキーマ更新 Task 1.2 ✓ APIエンドポイント追加 Task 2.1 ✓ フロントエンドコンポーネント作成 AIは、tasks.mdに記載されたタスクを順番に実行していきます。各タスクが完了するたびに、進捗が表示されます。 仕様が明確なので、AIの出力も予測可能です。「データベーススキーマ更新」タスクでは、予想通り user_2fa テーブルが追加されます。「APIエンドポイント追加」タスクでは、 POST /api/auth/2fa/enable 、 POST /api/auth/2fa/verify といったエンドポイントが実装されます。 もし問題が発生した場合でも、どのタスクで問題が起きたかが明確なので、デバッグが容易です。タスクは小さな単位に分割されているため、問題の切り分けがしやすいのです。 Step 4: アーカイブと知識の蓄積 実装が完了し、テストも通ったら、変更をアーカイブします。 # コマンドライン、またはAIアシスタントに依頼 /openspec:archive add-profile-filters または、自然言語で: このコマンドを実行すると、以下のことが起こります: 開発者: 「変更をアーカイブして」 AI: 「変更をアーカイブします...」 *openspec archive add-profile-filters --yes* ✓ 仕様が更新されました openspec/changes/add-2fa/specs/auth/spec.md (差分)が、 openspec/specs/auth/spec.md (マスター仕様)に統合されます openspec/changes/add-2fa/ ディレクトリが削除されます Git履歴に、この変更が記録されます 結果として、openspec/specs/フォルダには常に最新の仕様が保たれ、openspec/changes/`フォルダには進行中の変更のみが残るという、クリーンな状態が維持されます。 CLAUDE.mdのみの場合との比較 ここで、従来のCLAUDE.mdのみを使った場合と、OpenSpecを使った場合を比較してみましょう。 CLAUDE.mdのみの場合の作業フロー: CLAUDE.mdをエディタで開く どこに2FAの仕様を書くべきか迷う(認証セクション?セキュリティセクション?新しいセクション?) 適当な場所に仕様を追記する AIにプロンプト:「2FAを追加して」 AIが大量のコードを生成する(1000行以上になることも) 生成されたコードをレビューしようとするが、何が変更されたのか分からない 既存の認証ロジックへの影響範囲が不明 他の開発者がCLAUDE.mdを更新していて、Gitコンフリクトが発生 コンフリクトを解決するが、自分の変更と他の人の変更が混ざって分かりにくい 結果: × 仕様がCLAUDE.md内で埋もれる(後から見つけるのが困難) × 変更履歴が残らない(なぜこの仕様になったかが不明) × チーム間での共有が困難(誰が何を変更したか分からない) OpenSpecを使用した場合の作業フロー: /openspec:proposal 二要素認証を追加 とコマンド実行 構造化されたファイル群が自動生成される proposal.md、tasks.md、design.md、spec差分を順番にレビュー 不明点があればAIと対話しながら詳細化 仕様に合意したら /openspec:apply で実装開始 タスクごとに進捗を確認できる 各タスクの成果物をその場でレビュー 問題があれば該当タスクだけを修正 完了後に /openspec:archive で知識として蓄積 他の開発者は別の変更提案で並行作業可能(コンフリクトなし) 結果: ✓ 変更内容が明確(dedicated directoryで管理) ✓ 影響範囲が把握できる(差分形式で表示) ✓ チーム全体で知識を共有(アーカイブで蓄積) ✓ 並行作業が可能(changes/以下で分離) 既存のAGENTS.md/CLAUDE.mdは不要? ここで疑問が生じます。「OpenSpecがあれば、AGENTS.md/CLAUDE.mdは不要なのか?」 答えは「 いいえ、併用が推奨されています 」です。 AGENTS.md/CLAUDE.mdとOpenSpecは役割が異なります。 AGENTS.md/CLAUDE.m dは、 全体的な指示を記述 します。プロジェクトのコーディング規約(「変数名はcamelCaseで書く」「ファイル名はkebab-caseで書く」など)、プロジェクト全体のアーキテクチャ(「MVCパターンを採用」「依存性注入を使う」など)、共通のワークフロー(「コミット前に必ずlintとtestを実行」など)といった、プロジェクト横断的なルールを定義します。 OpenSpec は、 個別機能の仕様を管理 します。認証機能の詳細な仕様、決済機能のAPI設計、検索機能のアルゴリズムなど、機能ごとの具体的な仕様を管理します。 両者は補完関係にあります。AGENTS.md/CLAUDE.mdが「プロジェクトの憲法」だとすれば、OpenSpecは「個別の法律」のようなものです。 OpenSpecは、AGENTS.md/CLAUDE.mdと統合するための特別なブロックを提供しています: <!-- OPENSPEC:START --> # OpenSpec 操作手順 この手順は、本プロジェクトで活動するAIアシスタント向けです。 以下のリクエスト時には常に `@/openspec/AGENTS.md` を開いてください: - 計画や提案に関する言及がある場合(proposal、spec、change、plan などの単語を含む) - 新機能の導入、互換性のない変更、アーキテクチャ変更、大規模なパフォーマンス/セキュリティ作業に関するもの - 曖昧な内容で、コーディング前に正式な仕様書が必要な場合 `@/openspec/AGENTS.md` で以下の内容を学習してください: - 変更提案の作成と適用方法 - 仕様書のフォーマットと規約 - プロジェクト構造とガイドライン この管理ブロックを維持し、「openspec update」で手順を更新できるようにしてください。 <!-- OPENSPEC:END --> このブロックを AGENTS.md に追加することで、AIアシスタントがOpenSpecの使い方を自動的に学習します。ユーザーが「新機能を追加したい」と言えば、AIは自動的にOpenSpecの変更提案を作成するようになります。上記のブロックは OpenSpec init 実行時に自動的に CLAUDE.md に追加されます。 他ツールとの比較 ここで、主要なSDDツールを比較してみましょう。OpenSpec以外にも、優れたSDDツールがいくつか存在します。 Kiro(AWS) Kiroは、AWSが開発したSDDツールです。 大規模プロジェクト向けに設計 されており、プロジェクトの方向性と個別機能の仕様を明確に分離する 2層構造 が特徴です。 .kiro/ ├── steering/ # プロジェクト方向性(変更頻度:低) │ ├── product.md # プロダクトのビジョン、目標、ターゲットユーザー、主要機能 │ ├── tech.md # 技術スタック、アーキテクチャ方針 │ └── structure.md # ディレクトリ構造、命名規則 └── specs/ # 機能仕様(変更頻度:高) └── add-2fa/ ├── requirements.md # 機能要件 ├── design.md # 技術設計 └── tasks.md # 実装タスク プロジェクト構造: steering/ フォルダには、プロジェクト全体の方向性を定義します。これは 変更頻度が低い情報 です。 product.md には、プロダクトのビジョン、目標、ターゲットユーザー、主要機能といった、プロジェクトの根幹を成す情報が記載されます。例えば、「このアプリケーションは、中小企業の経理担当者をターゲットとした経費精算システムです。主要機能は、経費の申請・承認・精算です」といった内容です。 tech.md には、技術スタック、アーキテクチャ方針、使用するライブラリなどが記載されます。「Next.js 15 + NestJS + PostgreSQLを使用」「マイクロサービスアーキテクチャを採用」「認証にはAuth0を使用」といった技術的な決定事項です。 structure.md には、ディレクトリ構造、命名規則、モジュール間の依存関係などが記載されます。「フロントエンドは /frontend 、バックエンドは /backend に配置」「コンポーネント名はPascalCaseで書く」といった構造的なルールです。 一方、 specs/ フォルダには、個別機能の詳細仕様を定義します。これは 変更頻度が高い情報 です。 各機能ごとにディレクトリを作成し、その中に requirements.md (機能要件)、 design.md (技術設計)、 tasks.md (実装タスク)を配置します。 Kiroの2層構造の利点: この2層構造により、プロジェクトの憲法( steering/ )と個別の法律( specs/ )が明確に分離されます。 steering/ を変更するのは慎重に行うべきです。なぜなら、すべての機能に影響するからです。一方、 specs/ は頻繁に変更されます。新機能を追加するたび、既存機能を修正するたびに更新されます。 この分離により、チーム間の役割分担も明確になります。プロダクトマネージャーやアーキテクトは steering/ を管理し、個別の開発者は specs/ を管理する、といった分業が可能です。 大規模プロジェクト(数十人のチーム、数年にわたる開発)では、この構造が非常に有効です。 Spec Kit(GitHub) Spec Kitは、GitHubが開発したSDDツールです。 新規プロジェクトを0から立ち上げる際に最適化 されており、プロジェクトの立ち上げから運用まで、すべてのフェーズをカバーする重厚なドキュメント構成が特徴です。 プロジェクト構造: specs/001-todo-app-git-oauth/ ├── spec.md # 機能仕様書 ├── checklists/ │ └── requirements.md # 品質チェックリスト ├── plan.md # 実装計画(技術選定) ├── research.md # Phase 0: 技術調査 ├── data-model.md # Phase 1: データモデル ├── contract/ │ └── openapi.yaml # Phase 1: API制約 ├── tasks.md # Phase 2: 実装タスク └── quickstart.md # 開発者ガイド Spec Kitの特徴は、 4つのフェーズ に分かれた開発プロセスです。 Phase 0: 仕様作成 Phase 0: 仕様作成では、何を作るかを定義します。 spec.mdには、機能の概要、ユーザーストーリー、受け入れ基準などが記載されます。「エンジニアとして、Google OAuthでログインできるようにしたい。ログインに成功したら、ダッシュボードにリダイレクトされる」といった内容です。 research.md には、技術調査の結果が記載されます。「認証ライブラリとしてNextAuth.jsとAuth0を比較した結果、NextAuth.jsを採用する。理由は、Next.jsとの統合が容易であり、無料枠が充実しているため」といった調査レポートです。 Phase 1: 設計 Phase 1: 設計では、どう作るかを設計します。 plan.md には、実装計画が記載されます。技術選定の詳細な理由、アーキテクチャ図、開発スケジュール、リスク管理などが含まれます。 data-model.md には、データモデルが記載されます。「Userテーブルには、id (UUID)、email (string)、name (string)、createdAt (timestamp)を含む」といった具体的なスキーマ定義です。 contract/openapi.yaml には、APIの仕様がOpenAPI形式で定義されます。これにより、型安全性が確保され、APIドキュメントも自動生成できます。 Phase 2: 実装 Phase 2: 実装では、具体的な実装ステップを実行します。 tasks.md には、実装タスクが列挙されます。「プロジェクト初期化」「データベース設定」「認証エンドポイント実装」「ログインUI作成」といった具体的なタスクです。 Phase 3: レビュー Phase 3: レビューでは、実装内容の動作確認を行います。 quickstart.md には、開発者ガイドが記載されます。環境構築手順、開発サーバー起動方法、テスト実行方法、デプロイ手順などが含まれます。新メンバーが参画したとき、このquickstart.mdを読めばすぐに開発を始められるようになっています。 さらに、 checklists/requirements.md には、品質チェックリストが含まれます。機能要件、非機能要件、テストカバレッジ、ドキュメント、コード品質など、各項目について確認すべき事項がリスト化されています。 Spec Kitの強み: Spec Kitは、 新規プロジェクトを0から立ち上げる際の完全なガイド として機能します。何をどの順番で行えばよいか、何を確認すべきかが明確なので、経験の浅いチームでも品質の高いプロジェクトを立ち上げられます。 また、OpenAPI連携により型安全性を確保できるのも大きな利点です。APIの仕様が変更されたら、自動的に型定義も更新され、フロントエンドとバックエンドの不整合を防げます。 GitHub Copilotとの統合も考慮されており、GitHub上のプロジェクトで特に威力を発揮します。 3ツールの比較表 3つのツールを表で比較すると、以下のようになります: 特徴 OpenSpec Spec Kit Kiro 対象 既存PJ (1→N) 新規PJ (0→1) 全プロジェクト 構造 2フォルダ (specs + changes) 4フェーズファイル 2層構造 (steering + specs) 主要ファイル proposal.md tasks.md spec 差分 spec.md + research.md plan.md + data-model.md tasks.md quickstart.md product.md tech.md structure.md requirements.md design.md tasks.md 変更管理 差分 + アーカイブ Git履歴 Git履歴 価格 無料(AIツール利用料のみ) 無料(AIツール利用料のみ) 有料(毎月 無料枠あり) どれを選ぶべきか それぞれのツールには明確な使い分けがあります。 OpenSpec は、 既存プロジェクトに導入したい場合に最適 です。すでに動いているプロジェクトに後から導入でき、学習コストが低く、複数の変更を並行して進めやすいのが特徴です。 「今のプロジェクトにSDDを導入したいが、大きな変更は避けたい」「チームメンバーが異なるAIツールを使っている」「複数の機能を同時並行で開発している」といった状況では、OpenSpecが適しています。 Spec Kit は、 新規プロジェクトを立ち上げる場合に最適 です。0から丁寧にガイドしてくれ、ドキュメントが重厚で、品質チェックリストも完備されているのが特徴です。 「新しいプロジェクトをこれから始める」「チームメンバーに経験の浅い人が多い」「品質を重視したい」「GitHub Copilotを使っている」といった状況では、Spec Kitが適しています。 Kiro は、 大規模で長期的なプロジェクトでしっかりした構造が必要な場合に最適 です。steeringとspecsの2層構造が強力で、プロジェクトの方向性と個別機能を明確に分離できるのが特徴です。 「数十人規模のチームで開発している」「数年にわたるプロジェクト」「プロダクトマネージャーと開発者の役割分担を明確にしたい」「予算がある(有料ツールを導入できる)」といった状況では、Kiroが適しています。 AIコーディングの進化 AIコーディングは、ここ数年で劇的に進化してきました。 第1世代 : コード補完の時代(2021年頃〜)では、GitHub Copilot、TabNineなどのツールが登場しました。これらは、コードの一部を書くと、次の行を予測して補完してくれるというものでした。開発者の生産性は向上しましたが、あくまで「補完」に過ぎず、開発者が設計し、コードを書くという基本は変わりませんでした。 第2世代 : 対話型コード生成の時代(2023年頃〜)では、ChatGPT、Claude、Cursorなどが登場しました。自然言語で「ユーザー認証機能を作って」と指示すると、完全なコードが生成されるようになりました。これは革命的でしたが、同時にVibeコーディングという問題も生み出しました。 第3世代 : 仕様駆動開発の時代(2025年〜)では、OpenSpec、Kiro、Spec Kitなどが登場しました。コードを書く前に仕様を定義し、AIと合意するというアプローチです。これにより、予測可能で、監査可能で、再利用可能な開発が実現されました。 開発者の役割の変化 仕様駆動開発の登場により、開発者の役割も変化しています。 第2世代のAIコーディングでは、開発者は「 AIのサポートでコードを書く 」という役割でした。AIが生成したコードをレビューし、修正し、統合するという作業が中心でした。 第3世代のAIコーディングでは、開発者は「 仕様を設計し、AIを操縦する 」という役割に変化しています。コードを書く作業の多くはAIに任せ、開発者は「何を作るべきか」を明確に定義することに集中します。 ただし、以下の点は変わりません: コードを読む能力、理解する能力は依然として重要 です。AIが生成したコードが正しいかどうかを判断するには、コードを読み解く力が必要です。 コードを書く作業はAIに任せていく のが今後のトレンドです。単純なCRUD操作、ボイラープレートコード、テストコードなどは、AIに任せることで効率化できます。 そして、 「何を作るべきか」を明確に定義する能力がより重要 になっていきます。曖昧な指示ではなく、具体的で明確な仕様を書ける能力が、これからのエンジニアに求められるのです。 チーム開発の改善 SDDは、チーム開発にも大きな改善をもたらします。 知識の蓄積と共有 が可能になります。仕様が文書として残るので、「なぜこの設計になっているのか」「どういう経緯でこの技術を選定したのか」が後から分かります。新しいメンバーが参画しても、仕様を読めば素早くキャッチアップできます。 品質の向上 も期待できます。予測可能な出力により、「期待と違う」というギャップが減ります。レビュー可能な変更により、仕様レベルでのレビューが可能になります。追跡可能な履歴により、問題が発生したときに、どの変更が原因かを特定しやすくなります。 まとめ この一年の学びを、3つのポイントにまとめます。 仕様は新しいソースコード AIとの協業において、明確な仕様が最も重要です。コードそのものよりも、「何を作るか」を定義する仕様の方が価値を持つ時代になりました。仕様さえあれば、AIがコードを生成してくれます。逆に、仕様がなければ、AIは迷走します。 AIとの協業には構造が必要 Vibeコーディングから脱却し、予測可能な開発へ移行する必要があります。感覚的にコードを書くのではなく、構造化されたプロセスでAIと協業することで、品質と生産性の両立が可能になります。 AIに振り回される開発から、AIを使いこなす開発へ 仕様駆動開発(SDD)により、より良いソフトウェアを効率的に構築できます。AIは強力なツールですが、それを使いこなすのは人間です。明確な仕様を定義し、AIを適切に操縦することで、真の生産性向上が実現されます。 さいごに 今回は試行錯誤を重ねる中で、今年になって流行りだした「仕様駆動開発(SDD)」と実現するためのツールについて書きました。今年は業務内外で学んだ生成AIツールやAzureリソースに関することなど幅広い内容のブログを投稿できたと思います。これからも業務関係なく学んだ内容を投稿していこうと思います。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post もうAIに振り回されない!OpenSpecで実現する予測可能なAI開発 first appeared on SIOS Tech. Lab .
こんにちは、サイオステクノロジーの佐藤 陽です。 「SIOS社員が今年一年で学んだこと」のアドベントカレンダー3日目です。 今回は、技術そのものというよりも、IT技術コミュニティの「運営」の話について書いていきます。 私は、2025年2月からJAZUG(Japan Azure User Group)静岡支部である「JAZUG Shizuoka」の運営を始めました。 自分は今年1年、「アウトプット力を更に高める」をテーマに動いてきており、その中核になったのが、このJAZUG Shizuokaの立ち上げでした。 運営を始めてから、気づけば1年弱が経ち、これまで3回のイベントを開催してきました。 第1回 JAZUG Shizuoka (2025年2月) 第2回 JAZUG Shizuoka (2025年6月) 第3回 JAZUG Shizuoka (2025年11月) 地方(静岡)でIT技術コミュニティを再興し、運営することで見えてきた「苦労」と、 それ以上に大きかった「メリット」について、振り返りを兼ねてまとめたいと思います。 地方でエンジニアをしていて「何か新しいことを始めたい」と思っている方の参考になれば幸いです。 なぜ静岡支部を立ち上げたのか? 東京では連日のように盛んなITイベントが開催されています。 しかし、静岡に住んでいると、時間やお金の都合で頻繁に参加することはできません。 「参加したいけれどできない」というもどかしさが常にありました。 オンラインで参加できるイベントもありますが、どこか受け身になってしまい、なかなか満足のいく体験には至っていませんでした。 それでも、エンジニアとして成長できる場として技術コミュニティへの強い憧れがありました。 もちろん静岡にもいくつか技術コミュニティはありますが、なかなか自分にマッチするものが見つからず…。 Azureコミュニティも以前は静岡に存在していたのですが、活動が休止している状態でした。 そんな折、ひょんなことからその以前の静岡のAzureコミュニティの方とつながる機会があり、そこからの流れでJAZUG本体の方とも繋がって、色々とお話をする機会をいただきました。 その過程で、 ないなら、自分がやってしまえばいいんだ。 と思い立ち、JAZUG Shizuokaの運営をスタートさせました。 初回イベント 意気込んで始めたものの、現実はそう甘くはありませんでした。 イベント公開後も想像していたよりも集まりは悪く、集客の難しさを痛感したスタートでした。 そのため会社の同僚や、知人のエンジニアに片っ端から声をかけて、なんとか最低限の参加者を募ることができました。 ただ、嬉しい誤算もありました。 参加者はなかなか集客に苦労しましたが、 登壇者に関しては、一般公募でLT(ライトニングトーク)枠が、すぐに定員に達しました。 地方にも、アウトプットしたい熱意を持ったエンジニアは確かにいる! と実感できたことは、運営を続ける大きなモチベーションになりました。 そんなこんなで初回のイベントは、参加者の皆さんのご協力もあり、大きなトラブルもなく終えることができました。 そこから第2回・第3回の開催へとつながっています。 「現地開催のみ」にこだわる理由 今の時代、オンライン配信を併用するハイブリッド開催が主流かもしれません。 オンラインにすれば全国から参加でき、集客人数も稼ぎやすいかと思います。 しかし、JAZUG Shizuokaでは あえて「現地開催のみ」 にこだわっています。 これは、オンライン要素があることで地方支部としての存在意義が薄れてしまうと考えたからです。 実際、現地に集まった参加者同士で話すと、 「あ、あの会社の方なんですね!」 といったローカルな共通点が見つかったり、地元のエンジニア事情などの「濃い話」で盛り上がったりすることが多々ありました。 これは、現地開催だからこそ生み出せた価値だと思っています。 そして今後もこの点は継続していきたいと思っています。 運営して得られたもの エンジニアとして、運営を通じて得られたメリットは非常に大きかったです。 1. 技術的な視野の広がり 自分ひとりで仕事をしていると、どうしても業務で触る機能や領域に知識が偏ってしまいます。 もちろん参加者として話を聞くだけでも勉強になりますが、運営(特に司会進行)を担うことで、「登壇者の話を誰よりも理解して、会場に橋渡ししよう」という良い意味でのプレッシャーが生まれました。 その結果、ただ漫然と聞くのではなく、他社の活用事例や普段触らないAzureの機能についても、以前より深く、自分事としてキャッチアップする姿勢が身につきました。 今後の個人的な課題 これに関連して、運営(司会)としては、LTで登壇してもらった後に、 「ありがとうございました。〇〇の技術って、やっぱり××なんですね。」 といった一言気の利いたコメントをしたいのですが、自身の技術力不足で、なかなかうまくコメントできないことも多くあります。 このあたりからも、やはり浅く広くでも知識を持っておきたいなと感じています。 2. コネクション 運営をするにあたって、今回であればJAZUGの方々とのつながりを持てたことが大きかったです。 また、X(旧Twitter)などで公募した際には、Microsoftの人や、界隈で著名な方にもリアクションをいただきました。 東京のITイベントに参加した際にも「あのJAZUG Shizuokaの!」といったことがあったりもしました。 こうしたつながりの一本一本はまだ細い線かもしれませんが、いつか大きなものにつながっていくのではないかと感じています。 3. 「場づくり」というスキル 技術力(ハードスキル)だけでなく、チームの成果を最大化する「場づくり」の力(ソフトスキル)の大切さを痛感しています。 運営を通じて必要となる「参加者が発言しやすい空気感を作る力」や「人を巻き込む力」は、そのままチームマネジメントにも通じるものがあると思います。 また、サードプレイスという、いつもとは異なる環境でこのような経験が出来ることは自身のキャリアに活きてくる部分と感じています。 まだまだ自分自身として未熟な部分ではありますが、このスキルの重要性を感じられたことは非常に大きな収穫であると感じています。 4. ITイベントへの参加率向上 当たり前ですが、運営メンバーなのでイベントには毎回参加します。 さらに、運営側の特権として、開催時期や場所、時間帯などをある程度自由に決められます。 自分は子供も小さく、なかなか関東(への遠征や、夜遅くに開催されるイベントへの参加が難しい状況です。 そういった場合、「自分が参加できる日時・場所」でイベントを開催してしまえばよいのです。 これはある種の職権乱用かもしれませんが、自分が確実に参加できる条件で場を作ることで、結果として自分自身の技術イベント参加率は確実に上がりました。 今後について これからは「細く長く」続けていきたいと思っています。 無理に規模を拡大するのではなく、継続することで信頼を積み重ねていきたいです。 願わくば、このコミュニティをきっかけに地元の企業同士のコラボレーションなどが生まれたら、最高だなと考えています。 ということで、是非JAZUG Shizuokaへのご参加の方お待ちしております! 開催のお知らせについては connpass や X を要チェックです! 最後に 地方在住で、なかなか参加するコミュニティなどが無くてもどかしく思っている方へ! いっそのこと、自分でコミュニティを立ち上げてしまうのはどうでしょうか? 地方でコミュニティを運営するのは、確かに集客などの面で大変です。 ですが、そこで得られる 繋がりや、運営の経験は、何物にも代えがたい資産になると思います。 今ではConnpassで公開するだけでイベントを開催できますし、SNSを利用して無償で宣伝も行えます。 仮に参加人数が集まらなかったり、うまくいかなくてもリスクはほとんど無いかと思います。 いずれ仲間はきっと見つかりますし、エンジニアとしての世界が間違いなく広がると思います。 是非検討してみてください!ではまた! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 1人がこの投稿は役に立ったと言っています。 The post 地方でIT技術コミュニティを1年間運営して得たもの first appeared on SIOS Tech. Lab .
こんな方へ特におすすめ これからエンジニアとしてのキャリアをスタートさせる方 未経験からエンジニアを目指しているけれど、不安を感じている方 IT業界やエンジニアという職業に興味がある、学生や他業種の方 概要 こんにちは。サイオステクノロジーのはらちゃんです。 「SIOS社員が今年一年で学んだこと」のアドベントカレンダー2日目です!記念すべき10本目のブログ執筆となります!! 早いもので、新卒で入社してから1年が経ちました。 今回は、この1年間どんな風に過ごしたか、何を学んだのか一緒に振り返っていきます。 私のスタート地点 私は大学時代、機械工学を専攻していました。普段は材料力学や流体力学といった、物理的なモノを相手にする毎日。そんな私がITエンジニアとして新卒入社したのですから、まさに異世界への挑戦でした。 ただ、まったくプログラミング言語に触れたことがないわけではありませんでした。研究室ではC#を扱い、ゲーム開発のようなことをしていました。そのため、幸いにも「プログラミング」という行為自体への抵抗感はありませんでした。 漠然と作っていくことの楽しさを感じていて、将来も型にハマらない自由な仕事をしたいと考えるようになりました。 入社直後 最初の壁 入社後最初の3カ月は、配属前の全体研修期間でした。ここでは主に、社会人としてのビジネスマナーや、エンジニアになるためのIT基礎知識を学びます。 私はここで「学生」と「社会人」のマインドセットの違いを強く感じました。 例えば、このような違いがあります。 学生時代は、与えられた課題に対して正解を出すこと、あるいは自分一人が納得できる成果物を作ることがゴールでした。しかし、社会人では「価値を生み出すこと」「チームで成果を出すこと」が求められます。 学生 社会人 評価基準 テストの点数 個人の研究成果 チームへの貢献度 ビジネス的な価値 時間感覚 比較的自由 コスト意識 責任の範囲 自分の行動範囲内 失敗しても自分が困るだけ 組織全体に影響が及ぶ プロとしての責任 コミュニケーション 仲の良い友人 年齢・立場の異なる多様な人 報告・連絡・相談の徹底 特に「報連相」の重要性は、頭で理解していても実践するのは難しく、最初はタイミングや伝え方によく戸惑いました。この期間に、技術者である前に一人のビジネスパーソンとしての基礎を叩き込まれたと感じます。 実務 第二の壁 いよいよSL(部署)に分かれて業務をしようというとき、ここで「趣味」と「仕事」の違いを感じました。 私は、大学の情報系学科で学ぶような「情報の基礎知識」がまったくありませんでした。インフラ、ネットワーク、OSなどの基盤知識がほぼゼロで飛び交う専門用語がまるで呪文のように聞こえました。 さらに、これまで一人でコードを書いていたため、チーム開発の経験が皆無でした。「Gitっておいしいの?」という状態で、バージョン管理という概念すらありませんでした。 「一人で動くコードが書ける」ことと、「プロとしてチームでシステム開発ができる」ことは、全くの別物だったのです。 当時の私のできること、できないことは明確に分かれていました。 できること コードを見ること、書くことへの免疫 モノづくりに対するポジティブなモチベーション できない、知らないこと 情報の基礎知識 チーム開発の作法 気付き はじめは疑問だらけでした。 エラーログを見ても何が書いてあるか分からない。先輩に質問しようにも、何が分からないのかが分からない。 しかし、もがき続ける中で、いくつかの重要な「気付き」がありました。 「分からない」を認める勇気 一人で抱え込んでも事態は悪化するだけだと痛感しました。勇気を出して「ここが分かりません」と発信したとき、先輩方は嫌な顔一つせず、丁寧に教えてくれました。 暗記ではなく「調べ方」を知る 膨大なITの知識を全て暗記するのは不可能です。重要なのは、エラーが出たときに「どういうキーワードで検索すればよいか」という、問題を解決するための「調べ方」を身につけることだと気付きました。 知識が知恵になる 最初はバラバラに見えていた知識(例えばLinuxコマンドとGitの操作)が、実務の中で繋がる瞬間が訪れます。 「あ、あの時のあれは、こういうことだったのか!」 というアハ体験。この積み重ねが、成長の実感に繋がりました。 また、技術との向き合い方だけでなく、チームで仕事をする上でのコミュニケーションについても、大きな意識の変化がありました。 仕事としてのコミュニケーション 「報連相」もたしかに重要ですが、今大切なのは「ザッソウ」だと感じました。 雑談 他愛のない話ができる人と仕事をする環境であれば、連絡や質問もスムーズです。 相談 上記のような安心感があれば、躊躇することなく人に相談できます。 チーム開発では、互いのタスクを把握していることで全体の進捗を把握し、納期を意識したスケジュール管理が行えます。 1人で抱え込むことは、チームにとっても当人にとっても利益のないことです。 とにかくやってみる 実プロジェクトが始まる前に、自己学習としてOJTに取り組みました。 そこでは「何をやりたいか」を重視していて、私はただひたすらに作りながら学ぶことを行いました。 具体的には、Webアプリケーション開発の全体像を把握するために、フロントエンドからデータベースまでの一連の流れを網羅的に学習しました。 私が取り組んだ基本的な構成は以下の図の通りです。 ユーザーが触れる画面(フロントエンド)には React 、データの処理やビジネスロジックを担うサーバーサイド(バックエンド)には Python 、そしてデータを保存するデータベースには MySQL を選定しました。 これらを組み合わせて一つのアプリケーションとして動作させることで、それぞれの役割や連携の仕組みを肌で感じることができ、Web開発の基礎体力をつける良い機会になりました。 また、この時期に並行して基本情報技術者試験の学習を行ったことも、業務で触れる知識を体系的に理解する助けになりました。「業務に絡めて理解する」ことが、資格取得への近道だと感じました。 上記のような開発をしながら、ライブラリやツールを活用してみたり、考えなければならないリスクに対する対策を考えてみたりと興味を持つことは強みになります。 このように、さまざまな技術に触れる時間のなかで、RAGを扱ったシステム開発が最も印象的です。 RAGとは、特定の情報源(社内データベース等)から関連情報を検索し、それを活用して大規模言語モデルがテキストを生成する技術です。AIが事実に基づかない情報を生成する現象(ハルシネーション)の対策の1つと言えます。 具体的なシステムの内容については こちら のブログで書いているので覗いてみてください。 ここで私は自身のAI相棒を作ろうと奮起しています。言語モデルはローカルで動かせる軽量さを重視し、Gemma(ジェマ)を用いています。 今、できること 1年前の自分と比べて、少しは胸を張って「成長した」と言えるようになりました。 技術面 チーム開発への参加 Gitを使ったバージョン管理、プルリクエストの作成、コードレビューの指摘対応などが、日常的な業務としてできるようになりました。 問題解決能力の向上 エラーが発生してもパニックにならず、ログを読み解き、仮説を立てて調査し、ある程度の問題は自己解決できるようになりました。 全体像の理解 自分が担当している機能が、システム全体の中でどのような役割を果たしているのか、アーキテクチャを意識して開発できるようになりました。 マインド面 学習意欲の向上 「分からない」ことが「怖い」ことではなく、「新しいことを知るチャンス」だと捉えられるようになりました。技術への好奇心が恐怖心を上回るようになりました。 プロとしての自覚 自分の書いたコードがサービスとして世に出て、ユーザーに使われることの責任感を持つようになりました。 他者への貢献意欲 まだまだ教えてもらうことが多いですが、新しく入ってくる後輩や、同じように悩んでいるチームメンバーに対して、自分の知見を共有したいと思うようになりました。 過去の自分へ伝えたいこと 1年前の、不安で押しつぶされそうだった自分に声をかけられるなら、こう伝えたいです。 周りの同期と比べて焦る必要はない。 一つひとつ向き合って、手を動かし続けていれば、必ず点と点が繋がる瞬間が来る。 完璧を目指さなくていい。 昨日の自分より少しでも前に進んでいれば、それで十分すごい。 これは、これから未経験でエンジニアの世界に飛び込もうとしている皆さんへのメッセージでもあります。 知識の有無よりも、「学び続ける姿勢」と「素直さ」があれば、絶対に大丈夫です。 まとめ 機械系出身、IT知識ゼロからのスタート。怒涛のような1年でした。 もちろん、まだまだ半人前で、学ぶべきことは山のようにあります。しかし、この1年間で得た「分からないことを乗り越える力」と「作る楽しさ」は、これからのエンジニア人生における最強の武器になると確信しています。 2年目も、初心を忘れず、技術を楽しみながら成長していきたいと思います! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 1人がこの投稿は役に立ったと言っています。 The post 基礎知識ゼロから新卒1年|仕事としての技術とマインド first appeared on SIOS Tech. Lab .
PS SLの佐々木です。 SIOS Tech Labアドベントカレンダー1日目になります! 今年からOSS推進フォーラムの鳥観図ワーキンググループのリーダーとして活動しています。 そこでOSS鳥観図WGの活動を今回は紹介させていただこうと思います。 OSS鳥観図ワーキンググループとは 「OSSを使いたいけど、○○の分野ではどのOSSがよく使われているのだろう?」 OSS鳥瞰図とは、こういったOSS初心者を手助けするために複雑多岐にわたるOSSを、視覚的に俯瞰できるようまとめたものです。鳥瞰図WG (旧クラウド技術部会)では世論の活用状況などを観察し、2014年からOSS鳥瞰図を毎年更新しています。 活動の基本方針 OSS利用者が、システムにOSSを採用・導入する際の手引きとなる情報を提供する OSS鳥瞰図を最新版に更新し、 OSSの選定をより安心感をもって、かつ短時間にできるよう手助けをする OSSに関する技術動向、日本国内事例等を広く集め、様々な形でOSSを活用する人たちに、プラスとなる情報を提供する 活動内容 鳥観図改版活動 OSS鳥観図WGでは毎年公開されているOSS鳥観図の改版を行うため、月に一度鳥観図に掲載するOSSの見直しを行っています。 具体的には鳥観図の新規追加、削除、カテゴリーの変更などを有識者たちで集まり議論し、来年度に掲載するOSSを決定しています。 新規追加では今年注目度が集まっているOSSの選定を行いWG内で議論し掲載するか決定しています。 削除やカテゴリー変更では掲載中のOSSにライセンスの変更がないか、機能が拡張され現在属しているカテゴリーが適切ではないのではないか、OSSの開発活動が活発に行われているか、セキュリティーで深刻な脆弱性が報告されていないかなど様々な観点で掲載中のOSSを検討し来年度の鳥観図を確定していきます。 OSS鳥観図宣伝活動 OSS鳥観図では様々なオープンソースのイベントに参加し発信活動を行っています。 OSC Open Source Summit etc… WG参加メンバー ワーキンググループには多くのメンバーが参加しており、大手のベンダーやOSSコミュニティ、参加者まで多岐にわたります。 鳥観図WGへの関わり方(コントリビューション方法) OSS鳥観図ワーキンググループでは参加メンバーを募集しています。 活動内容は上記記載した通りですが、月に一度2時間程度のWGでのディスカッションと担当カテゴリのOSSの調査がメインの活動になります。 もし活動に興味のある方はka-sasaki@sios.comまでご連絡ください。 またこの活動以外にも実際に鳥観図を見て、追加してほしいOSSの提案や脆弱性報告など様々な提案をGithub Issueで募集しています。 是非とも貴重なご意見お待ちしています。 https://github.com/ossforumjp/oss-choukanzu/issues 鳥観図WGのホームページ https://ossforum.jp/index.php/choukanzu-wg/ ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post OSS鳥観図ワーキングループの活動紹介 first appeared on SIOS Tech. Lab .
はじめに 前回は、StatefulSetと永続ボリューム(PV/PVC)を使い、データが消えないDBコンテナを起動しました。 しかし、データベースはアプリケーションから接続されて初めて価値があります。そのため今回はアプリコンテナとDBコンテナの接続方法を学びます。 前提条件 Kubernetesで、Pod同士をどうやって通信させるのか仕組みを知りたい方 DBコンテナを立てることはできたが使用出来ていない状態の方 アプリコンテナとDBコンテナを接続するための基本概念 コンテナ同士を接続する方法はいくつかありますが、Kubernetesでは推奨される接続方法が決まっており、単純な接続方法ではうまくいきません。特にDB接続では、ポート番号や認証情報(Secret)をアプリコンテナに適切に渡す必要があるほか、DBコンテナの動的なスケーリングや再起動によるIPアドレスの変動が接続安定性の課題となります。 このような固有の課題を解決するためには、Kubernetesのネットワーク層におけるServiceやDNSの仕組みを理解することが重要です。この記事では、DB接続における安定性を向上させるために、ServiceとDNSの利用方法に焦点を当て、その役割や実践的な活用法を解説します。 直接接続の問題点 最も単純な接続方法は、DBコンテナ(Pod)のIPアドレスを調べ、アプリの設定ファイルに直接記述する方式です。しかし、この方法には致命的な問題があります。Podは再起動するとIPアドレスが変わってしまうという点です。ノードの障害、設定変更による再デプロイ、負荷分散による再スケジューリングなどの問題が発生すると、古いPodは破棄され、新しいPodが作られます。この時、IPアドレスは変わってしまいます。 直接接続ではDBが再起動するたびにアプリの設定ファイルを書き換え、再起動しなければならず手間がかかります。 Serviceの仕組み Kubernetesでは、PodのIPアドレスが変動する問題を解決するために「Service」というリソースを利用します。Serviceは一意の名前を持ち、内部DNSを介してアクセス可能です。これにより固定的なDNS名を提供することができ、アプリケーションはこのDNS名を使用して安定した通信を実現できます。 KubernetesのDNSの仕組み Serviceを利用することで、PodのIPアドレスが変わる問題を解決できます。しかし、ServiceのIPアドレスをアプリケーションに設定する手間が残ります。この問題を解決するのがKubernetesのDNSです。通常、DNSはドメイン名とIPアドレスを対応させる役割を持っています。一方、Kubernetesクラスターには専用のDNSサーバーが標準で組み込まれており、Service名とIPアドレスを対応づける機能を提供します。Kubernetesでは、Serviceを作成すると、そのサービス名とIPアドレスの対応が自動的にDNSサーバーに登録されます。 この仕組みによりKubernetesでのPod間の接続は完全修飾ドメイン名(<Service名>.<Namespace名>.svc.cluster.local)を使用して実現できます。サービス名とネームスペース名を指定することで、Pod間通信が可能になります。 また、本記事ではDNSの仕組みの理解のために完全修飾ドメイン名を使用していますが、同じネームスペース内に存在するアプリケーションからServiceに接続する際にはサービス名だけで接続が出来ます。 YAMLファイルの作成例 これまで、アプリコンテナとデータベースコンテナの接続方法について解説しました。ここからは、具体的なYAMLファイルの例を示し、ServicesやKubernetesのDNSをどのように設定するのかについて解説します。 DBコンテナ側の設定 DBコンテナの設定(接続されるコンテナ) apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql spec: serviceName: "mysql-service" replicas: 1 selector: matchLabels: app.kubernetes.io/name: mysql # (A) Serviceはこのラベルを基準にPodを探す。 template: metadata: labels: app.kubernetes.io/name: mysql # (A) Serviceに見つけてもらうためのラベル。 spec: containers: - name: mysql-container image: mysql:8.0 env: # ... 省略 ... ports: - containerPort: 3306 # (B) このPodが待ち受けるポート。ServiceのtargetPortと一致させる。 volumeClaimTemplates: - metadata: name: mysql-storage spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "standard" resources: requests: storage: 1Gi Serviceの設計(接続の窓口) apiVersion: v1 kind: Service metadata: name: mysql-service # KubernetesのDNSに登録される名前。この名前を使って他のコンテナからアクセス可能になる。 spec: selector: app.kubernetes.io/name: mysql # (A) このラベルを持つPodを探す。 ports: - protocol: TCP port: 3306 # クライアントが接続するポート番号。 targetPort: 3306 # (B) Podのコンテナが待ち受けているポート。StatefulSetのcontainerPortと一致させる。 metadata.name: mysql-service :サービス名がKubernetesのDNSに登録されます。このサービス名とネームスペース名があれば他のコンテナから接続ができます。 selector:Serviceが接続先のPodを決定するためのラベルセレクターです。ここでは、`app.kubernetes.io/name: mysql` というラベルが付けられたPodを対象とします。このラベルセレクターを使用してServiceは指定されたラベルを持つすべてのPodに接続します。 port: 3306:クライアントが接続するポート番号です。アプリケーションはこのポートに向けて通信します。 targetPort: 3306:Serviceが受け取った通信を転送するPodの内部ポート番号です。ここでは3306 番ポートに転送されます。 アプリコンテナ側の設定 apiVersion: apps/v1 kind: Deployment metadata: name: wordpress labels: app: wordpress # Podの識別用ラベル。 spec: # ... 省略 ... template: metadata: labels: app: wordpress spec: containers: - image: wordpress:6.2.1-apache name: wordpress env: - name: WORDPRESS_DB_HOST value: mysql-service.default.svc.cluster.local # 完全修飾ドメイン名を使用してDNSで解決する。 # ... 省略(DBのパスワードやユーザーの設定) ... - name: DB_PORT value: "3306" value: mysql-service:Serviceの名前を元にDNSを使ってIPアドレスを解決し、そのIPアドレスに対して接続を試みるための設定です。 おわりに 今回は、ServiceとDNSを活用したコンテナ同士の接続方法について解説しました。これらの技術を利用することで、PodのIPアドレスが変動しても影響を受けることなく、安定した接続を実現できます。 次回からは、Kubernetes内部のデータベースコンテナを外部に公開する方法について、2回にわたり解説していきます。 参考文献 https://kubernetes.io/docs/concepts/services-networking/service/ https://kubernetes.io/ja/docs/concepts/services-networking/dns-pod-service/ https://kubernetes.io/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/ ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post コンテナDB実践シリーズ④:アプリコンテナからDBコンテナへの接続 first appeared on SIOS Tech. Lab .
今号では、sftp コマンドを使ったファイル転送の方法について説明します! sftp とは sftp とは SSH File Transfer Protocol の略であり、暗号化された通信によって安全にファイルを送受信することができる仕組みです。 以前は ftp によるファイルの送受信が主流でしたが、通信を暗号化する仕組みがないため、内容が盗聴される可能性がありました。 そこで、すべてのデータを暗号化して送信することができる sftp が使用されることになりました。 主な用途としては、システム間でのファイルの送受信や、Web サーバへ各コンテンツ (html、css、画像ファイル) のアップロードなどがあります。 なお、今回は Linux や Windows 上のターミナルで sftp コマンドを使う前提で説明します。 基本の書式 リモートサーバへ接続 sftp ユーザ名@ホスト名 の書式で実行します。 例: $ sftp ruser@172.30.10.10 ruser@172.30.10.10's password: Connected to 172.30.10.10. sftp> ※パスワード認証の場合、リモートユーザのパスワードが求められます。 リモートサーバから切断 exit もしくは bye を実行します。 例: sftp> exit 現在のディレクトリ (リモート側) を表示 pwd コマンドを実行します。 例: sftp> pwd Remote working directory: /home/ruser 現在のディレクトリ (ローカル側) を表示 lpwd コマンドを実行します。 例: sftp> lpwd Local working directory: /home/luser ファイル一覧 (リモート側) を表示 ls を実行します。 例: sftp> ls 1.log 2.log 3.log dir1 dir2 ruser-file -l オプションを付けると、各ファイルやディレクトリの詳細を表示します。 sftp> ls -l -rw-rw-r-- 1 ruser ruser 0 Nov 17 01:04 1.log -rw-rw-r-- 1 ruser ruser 0 Nov 17 01:04 2.log -rw-rw-r-- 1 ruser ruser 0 Nov 17 01:04 3.log drwxrwxr-x 2 ruser ruser 6 Nov 17 01:06 dir1 drwxrwxr-x 2 ruser ruser 6 Nov 17 01:06 dir2 -rw-rw-r-- 1 ruser ruser 0 Nov 17 01:04 ruser-file ファイル一覧 (ローカル側) を表示 lls を実行します。 例: sftp> lls 1l.log 2l.log 3l.log local-dir luser-file -l オプションを付けると、各ファイルやディレクトリの詳細を表示します。 sftp> lls -l total 0 -rw-r--r--. 1 luser luser 0 Nov 17 01:05 1l.log -rw-r--r--. 1 luser luser 0 Nov 17 01:05 2l.log -rw-r--r--. 1 luser luser 0 Nov 17 01:05 3l.log drwxr-xr-x. 2 luser luser 6 Nov 17 01:07 local-dir -rw-r--r--. 1 luser luser 0 Nov 17 01:05 luser-file ディレクトリ (リモート側) を移動 cd ディレクトリ名 の書式で実行します。 例: sftp> cd dir1 ディレクトリ (ローカル側) を移動 lcd ディレクトリ名 の書式で実行します。 例: sftp> lcd local-dir 続いて、一番重要なファイル転送についてのコマンドです。 ファイルのダウンロード (リモート→ローカル) get リモート側のファイル名 の書式で実行します。 例: sftp> get ruser-file Fetching /home/ruser/ruser-file to ruser-file sftp> lls 1l.log 2l.log 3l.log local-dir luser-file ruser-file リモート側のファイル名の後に 任意のファイル名 を付けると、そのファイル名で保存されます。 sftp> get ruser-file ruser-file.bkp Fetching /home/ruser/ruser-file to ruser-file.bkp sftp> lls 1l.log 2l.log 3l.log local-dir luser-file ruser-file.bkp ファイルのアップロード (ローカル→リモート) put ローカル側のファイル名 の書式で実行します。 例: sftp> put luser-file Uploading luser-file to /home/ruser/luser-file luser-file 100% 0 0.0KB/s 00:00 sftp> ls 1.log 2.log 3.log dir1 dir2 luser-file ruser-file リモート側のファイル名の後に 任意のファイル名 を付けると、そのファイル名で保存されます。 sftp> put luser-file luser-file.bkp Uploading luser-file to /home/ruser/luser-file.bkp luser-file 100% 0 0.0KB/s 00:00 sftp> ls 1.log 2.log 3.log dir1 dir2 luser-file.bkp 複数ファイルの一括ダウンロード (リモート→ローカル) mget リモート側のファイル名パターン の書式で実行します。 例: sftp> mget *.log Fetching /home/ruser/1.log to 1.log Fetching /home/ruser/2.log to 2.log Fetching /home/ruser/3.log to 3.log sftp> lls *.log 1.log 2.log 3.log 複数ファイルの一括アップロード (ローカル→リモート) mput ローカル側のファイル名パターン の書式で実行します。 例: sftp> mput *.log Uploading 1l.log to /home/ruser/1l.log 1l.log 100% 0 0.0KB/s 00:00 Uploading 2l.log to /home/ruser/2l.log 2l.log 100% 0 0.0KB/s 00:00 Uploading 3l.log to /home/ruser/3l.log 3l.log 100% 0 0.0KB/s 00:00 sftp> ls *.log 1l.log 2l.log 3l.log sftp コマンドのオプション sftp コマンド の基本的なオプションをご説明します。 ※すべてのオプションはご紹介せず、よく使用されると考えられるものを抜粋しています。 -i 秘密鍵のファイル 公開鍵認証で接続する場合、-i の後に使用する秘密鍵のファイルを指定します。 $ sftp -i ~/.ssh/id_rsa ruser@172.30.10.10 -P ポート番号 SSH/SFTP が 22番ポート (デフォルト) 以外で動作している場合、該当するポート番号を指定します。 $ sftp -P 10022 ruser@172.30.10.10 -v 接続時の詳細なデバッグ情報を表示します。 なお、このオプションには 3段階あり、-vv にするとさらに詳細なデバッグ情報が、-vvv にすると最も詳細なデバッグ情報が表示されます。 $ sftp -v ruser@172.30.10.10 次号について 次号では、sftp と同じくファイル転送を担う rsync についてご紹介します! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 知っておくとちょっと便利!sftp コマンドを使ったファイル転送 first appeared on SIOS Tech. Lab .
こんにちは! 今月も「OSSのサポートエンジニアが気になった!OSSの最新ニュース」をお届けします。 11/4、LPI-Japan は Linux 技術者認定「LinuC」の上位認定「LinuC レベル3 プラットフォームスペシャリスト」と「LinuC レベル3 セキュリティスペシャリスト」の提供を開始すると発表しました。 LPI-Japan、Linux技術者認定「LinuC」の上位認定を刷新 https://japan.zdnet.com/article/35240027/ 11/4、日経新聞の Slack に不正ログインが確認され、約1万7000人分の情報が流出した可能性があると発表しました。 業務用チャット「スラック」への不正ログインと情報流出について https://www.nikkei.co.jp/nikkeiinfo/news/information/1393.html 11/14 (米国時間)、Red Hat は 新バージョン RHEL 10.1 および RHEL 9.7 の一般提供を開始しました。 Red Hat、Red Hat Enterprise Linux最新版で現代 IT に向け進化した基盤を提供 https://www.redhat.com/ja/about/press-releases/red-hat-delivers-evolving-foundation-modern-it-latest-version-red-hat-enterprise-linux ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 【2025年11月】OSSサポートエンジニアが気になった!OSS最新ニュース first appeared on SIOS Tech. Lab .
こんにちは、サイオステクノロジーの佐藤 陽です。 先日、毎年恒例のMicrosoft Igniteが開催され、様々な機能のリリースが発表されました。 今回は、その中でも個人的にインパクトが大きいと感じた「Foundry IQ」を取り上げます。 なお、本記事は現時点で公開されている紹介記事やドキュメントを読んだうえでの 所感ベース 自分が気になった点に特化 とした内容になっています。 実際に触ってみての検証は今後別途まとめる予定ですので、その点ご承知おきください。 Foundry IQとは Foundry IQは 「a unified knowledge layer for agents(エージェントのための統一された知識レイヤー) を提供する 」 と述べられています。 この定義をパッと聞いただけだと「結局これは何なの?」といった点が分かりづらいですよね。 そこでまず、現状のRAGの課題を整理し、それをFoundry IQがどう解決しようとしているのかを順番に見ていきます。 現状のRAGの課題 これまでRAGにおいて独自のナレッジを扱うにあたっては、以下のような理由から複雑な構成・運用になりがちでした。 ナレッジの内容ごとのパイプライン設計 ナレッジに対するアクセス制御の複雑さ Foundry IQは、これらの課題を解決するために設計されています。 1.ナレッジごとのパイプライン設計の負担 ナレッジを格納する際、すべてのデータに対して同じ処理を行っていては、期待する回答精度が得られないことが多いです。 例えば、以下のような観点で処理を変えたくなります。 ファイル形式の多様性: PDF、Office系ファイル、画像、音声 etc. データ構造の違い: 図表が多いファイル or 文章が多いファイル 専門性の違い: 専門用語が多いファイル or 一般的な情報が多いファイル これらの違いによって、データによって前処理の内容やチャンクサイズ、ベクトル化の際の次元数などを適切に切り替えていく必要があります。 また、1つの会社内で導入するにあたって、この「ナレッジの性質」は部署ごとに様々です。 それぞれの部署ごとにこう言ったパイプラインを細かく設計する必要がありますし、 新しくRAGを利用したい部署が出てきた場合、また部署のデータの特性に合わせて新規にパイプラインを設計・構築する必要があります。 また、上記の図はIndexer側の処理の話でしたが、Retrieverも同様です。 ナレッジごとに検索手法(キーワード検索、ベクトル検索、ハイブリッド検索、リランキング方法 etc.)を切り替える必要が出てきます。 このように、データの種別ごとにIndexerやRetrieverをここに設計し、メンテナンスしていくことは RAGを運用していくチームにとっても非常に大きな負担となっています。 2.アクセス制御の複雑さ 様々なナレッジをナレッジストアに登録したとしても、すべてのユーザーがすべてのナレッジにアクセスしてよいとは限りません。 例えば、役員会議用の資料をナレッジストアに登録した場合、一般社員はそのナレッジをコンテキストとした回答は得られないようにするべきです。 現状、Azure AI SearchなどでEntra IDと連携したアクセス制御を「フルマネージドで」実現することは難しく、 自前でEntra IDの情報とAI Search上のデータを紐づけてアクセス制御を実装・運用していく必要があります。 ただ、社内における部署異動や権限の追加/削除など、IDまわりの運用は日々変化します。 それらをすべてRAG側で追いかけ続けるのは、RAGの運用チームにとって大きな負担になります。 このように、既存のRAGでナレッジを適切に運用していくためにはかなりの時間とエネルギーを要します。 これが、今のRAG開発が持つ一番の「辛み」だと感じています。 Microsoft Igniteで発表されたFoundry IQ こうした課題を解決してくれるのがAzure Foundry IQです。 一言で言ってしまうと、「ナレッジごとのパイプライン構築」や「複雑なアクセス制御の実装」といった部分を、いい感じに一括してFoundry IQ側で引き取ってくれるサービス、というイメージです。 (※あくまでイメージ図です) このようにしてFoundry IQ では、RAGまわりの世界観を次のように変えます。 「ナレッジベース(Knowledge Base)」という箱をまず作る そこに、Blob / SharePoint / Web などのデータソースを「つなぐ」 この時点で様々なパイプライン設計・実装をFoundry IQで吸収する 複数のエージェントやアプリケーションから、このナレッジベースを 1つのAPI として参照する つまり、エージェント側やアプリケーション側でIndexerやRetriverの複雑なパイプラインを考慮数る必要はなく 1つのAPIにアクセスすることで、容易にナレッジを利用できるようになります。 Microsoftが出している Foundry IQのブログ記事 のタイトルも「 Unlocking ubiquitous knowledge for agents 」となっており、 まさにこういった部分を狙った機能であることがうかがえます。 Foundry IQの注目ポイント コンセプトは分かったとして、実際何が嬉しいのか? 特徴的だと感じたポイントを3つに絞って見ていきます。 1.データ投入とナレッジ管理 Foundry IQでは、インデックスされたデータとリモートデータをまたいで、同一のナレッジベースとして管理することが可能です。 データタイプ データソース例 インデックス型ソース Blob Storage, Azure AI Search Indexes etc. リモートソース M365 SharePoint, Web etc. このうちインデックス型データソースに対しては、コンテンツの取り込み、チャンク戦略、ベクトル化などを一通り自動で行ってくれます。 そして、これらのデータソースごとにパイプラインを構築したり、Retrieverの戦略を個別に設計したりする必要はない、と述べられています。 つまり、「取り込みたいデータソースをポータル上で選ぶだけで、あとはデータの内容に基づいてよしなにやってくれる」ようなイメージです。 また、リモートソースをそのまま読みに行けるのも大きなポイントです。 これまではSharePoint上のデータについても、一度BlobなどにコピーしたうえでAI Searchにインデックスするのが一般的でした。 この場合、元データの更新と同期をとる必要があり、どうしても処理が複雑になりがちでした。 その点、リモートデータを直接見に行き、常に最新のデータを参照できるのは非常に大きな強みだと思います。 余談 これまでのAzure AI Searchにも「データのインポート」機能があり、ワンクリックでデータのインデクシングを行うことができました。 Foundry IQは、これをより強化した機能、というイメージで個人的には捉えています。 公式ドキュメントにもFoundry IQの基盤はAzure AI Searchである旨の記載があります。 おそらく、AI Searchのデータインポート機能にLLMの力を組み合わせることで、より最適なチャンキングなどを行っているのではないかと予想しています。 2.Agentic Retrieval(エージェント型検索) 次のポイントは、検索エンジン自体が「エージェント化」しているという点です。 従来のRAGは、ざっくり言えば、 ユーザーの質問をEmbeddingする ベクトルDBから類似ドキュメントをk件取る LLMに「質問+コンテキスト」を渡して回答させる というフローが基本でした。 Foundry IQ が掲げている Agentic Retrieval では、ここに「プランニング」と「反復」が入り込みます。 質問の意図を解釈し、 どのデータソースから どの順番で どの粒度で 取ってくるべきかを推論する 初回検索で十分なコンテキストが得られなければ、クエリを書き換えて再検索する 必要に応じて、関連するサブクエリを自動的に発行する さらに、内部パラメータとして「どの程度深く考えてから答えるか(Retrieval Reasoning Effort)」を調整できるようになっています。 FAQレベルの簡単な質問 → 浅く・速く 複雑な推論や調査タスク → 深く・時間をかけて といったユースケースごとのチューニングが可能になるイメージです。 3.アクセス制御 最後はアクセス制限に関してです。 普段RAGの開発をしている自分からすると、ここが一番大きなポイントに感じています Microsoftのブログには、ざっくり次のような点が記載されています(意訳)。 設定済みかつサポートされているナレッジソースに対するユーザー権限を尊重する。 リモートSharePointナレッジソースの場合、Microsoft Purviewのデータ分類と機密ラベルが、インデックス作成および検索パイプラインを通じて尊重される。 今まで自前で制御しなくてはならなかったアクセス制御の部分を、Foundry IQ側で巻き取ってくれるのはこの上なくありがたいです。 なお1.の「設定部分」に関してはまだ詳細を追いきれていませんが、Entra ID基盤上に構築されているサービスであることを踏まえると ここは簡単に設定できる方向で仕上げてくれることに期待したいところです。 ブラックボックス化というトレードオフ ここまで読むと、 Foundry IQ さえ使っておけば間違いないのでは? という印象を持たれるかもしれません。 ただ、エンジニア視点で見ると、「チューニングの余地がかなり減ってしまった」という印象も受けました。 RAG の世界には、職人芸に近いチューニングポイントがいくつもあります。 チャンクサイズとオーバーラップ率 階層構造チャンク / セマンティックチャンクの使い分け Embeddingモデルの選定(汎用 vs ドメイン特化) 再ランキングのON/OFF、スコアのしきい値 Foundry IQ はこういった部分を大幅に巻き取ってくれている一方で、 逆に言えば、これらに直接手を入れる余地は意図的に小さくなっています。 極端に専門用語が多い業界 規制産業で、誤答率を極限まで下げたい案件 などでは、 もう少しRAGの中身を触らせてほしい… という欲求が出てくるかもしれません。 FoundryIQのようにブラックボックス的に大半の処理を行ってくれるのは大きな強みですが、同時に「RAG職人の腕の見せ所が減る」という側面もある点は、頭の片隅に置いておいたほうが良さそうです。 とはいえ、最近のAIの進歩を考えると、「RAG職人」が頑張って細かいチューニングをするよりも、AIに任せた方が良いアウトプットを出す可能性も十分にあります。 このあたりは、実際に使ってみて評価していくフェーズかなと思います。 導入時の注意ポイント 最後に、これは Foundry IQ に限らず、すべてのRAGに言える話ですが、 Garbage In, Garbage Out の原則は、一切変わりません。 元のデータソース管理場所がゴミ屋敷状態 新規 (1).docx 、 最終版_本当に今度こそ最終.pptx が乱立し、どれが最新か分からない 権限設定が形骸化 「よく分からないので Everyone にフルアクセスつけました」 といった環境のまま Foundry IQ とつなぐと、 高い確率で「自信満々に間違ったことを言うエージェント」か、 「見せてはいけない情報をさりげなく提案してしまうエージェント」が生まれます。 Foundry IQ は、 接続と検索エンジンの負担を大きく軽減してくれる ツールですが、 「データガバナンスそのものを自動で何とかしてくれる魔法」ではありません。 むしろ、Foundry IQ のようなツールを導入したとしても、 情報資産の棚卸し メタデータ設計 権限ポリシーの整理 といった 地味だが本質的な仕事 は結局必要になる、という印象です。 まとめと今後 今回はMicrosoft Igniteで発表された「Foundry IQ」についてご紹介しました。 Foundry IQを利用することによって、これまで煩雑な設計・管理が必要だった部分が大幅に削減されることが期待できます。 一方で、それによってチューニングポイントがかなり減ってしまうため、 特殊な業界のユースケースなど、マネージドな仕組みだけでは対応しきれないケースも出てくるかもしれません。 今回はMicrosoftの紹介記事を読んでの所感ベースかつ、RAGに特化した内容でした。 次回以降は実際にFoundry IQを使ってみつつ、エージェントとして使うならではの部分や・使ってみた感想などをお伝えできればと思います。 ではまた! 参考文献 Foundry IQ: Unlocking ubiquitous knowledge for agents Foundry IQ: ナレッジを最大限活用する Foundry IQ ナレッジ ベースを Foundry Agent Service に接続する ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 1人がこの投稿は役に立ったと言っています。 The post Foundry IQ は RAGにとっての銀の弾丸となりえるか?【Microsoft Ignite 2025 Recap】 first appeared on SIOS Tech. Lab .
こんな方へ特におすすめ ストップウォッチ作成の記事 を読んだ方 自作アプリを初期起動と共に実行させたい方 簡単にPythonのアプリを開発したい方 概要 こんにちは。サイオステクノロジーのはらちゃんです!今回9本目のブログ執筆です。 前回はストップウォッチアプリを開発しました。しかし、コードのままだと逐一コマンドで起動する必要があり面倒です。 そこで今回は、もっと便利に活用するために自動で起動させる方法を簡単3ステップでお伝えします。 EXE化ってなに? はじめに、”EXE(エグゼ)化”という変換の概要をご説明します。 EXE化とは、 「 プログラミング言語(Pythonなど)の翻訳機と、プログラムの指示書をひとまとめにして、誰でもワンクリックで動かせる状態にすること 」 です。 EXE化の仕組み stopwatch.py はただの「設計図」のようなもので、動かすにはPythonという「工具」と、Tkinterという「部品」が必要です。そのため、EXE化する前のプログラム単体ではアプリを起動させることができません。 PyInstallerは、「設計図(スクリプト)」「工具(Python本体)」「部品(ライブラリ)」の全てを一つにまとめて、 StopWatch.exe という「完成品(実行ファイル)」を製造します。 そのため、EXE化の工程を経てようやくアプリがどこでも起動できる準備が整います。 この仕組みはよく料理に例えられます。 「レシピ(指示書)」を動かすには、受け取る相手のPCに「キッチン(Python環境)」と「調理器具(ライブラリ)」が完備されている必要があります。 相手側で用意する手間を省くために、このレシピをプロのシェフごと箱詰めにして「お弁当」にするのです。 EXE化のメリット・デメリット 項目 EXE化のメリット EXE化のデメリット 起動 ダブルクリック一発 展開処理の時間がかかる 配布 相手にファイルを渡す ファイルサイズが大きくなる コード ダブ中身が見えにくくなる コードの修正ができない 前提条件 Windows 上で作業すること Python 3.8+ がインストールされていること pyinstaller をインストール可能であること Step1:EXE化 さっそく箱詰めしていきましょう。 .bat ファイルの作成 この.batファイルは、PythonスクリプトをEXEファイルに変換する「PyInstaller」というツールを実行するためのものです。 これを実行すると、 stopwatch.py から StopWatch.exe を作成します。 build_windows.bat @echo off REM PythonのEXE化ツール「PyInstaller」をインストールします pip install pyinstaller echo. echo --- Building StopWatch.exe --- echo. REM PyInstallerを実行します REM --onefile: 関連ファイルをすべて1つのEXEにまとめます REM --noconsole: GUIアプリ実行時に後ろで黒いコンソール画面が出ないようにします pyinstaller --onefile --noconsole --name StopWatch stopwatch.py echo. echo --- Build finished! --- echo `dist` フォルダ内に `StopWatch.exe` が作成されました。 echo. pause Step2:スタートアップへの登録 .ps1 ファイルの作成 この.ps1ファイルは、EXEファイルをWindowsの「スタートアップ」フォルダに登録し、PC起動時に自動実行するためのスクリプトです。 create_shortcut.ps1 param( [string]$TargetPath = "C:\Users\YourName\Documents\TIMER\dist\StopWatch.exe", [string]$ShortcutName = "StopWatch.lnk" ) # (以下は変更不要) $startup = [Environment]::GetFolderPath('Startup') $w = New-Object -ComObject WScript.Shell $sc = $w.CreateShortcut((Join-Path $startup $ShortcutName)) $sc.TargetPath = $TargetPath $sc.WorkingDirectory = Split-Path $TargetPath $sc.Save() Write-Host "Shortcut created in: $startup" Step3:実行 いよいよアプリの起動です。以下のコードを順に実行してください。 必ず、Windows上で作業するように注意してください。WSL(Linux)上でPyInstallerを実行しようとしてもエラーになります。 PowerShell # "cd" の後に、stopwatch.pyがあるフォルダのパスを入力します cd C:\Users\YourName\TIMER もしコードがWSL上にあるなら、Windows上にダウンロードされるようにツールのインストールも行ってください。 PowerShell pip install pyinstaller PowerShell pyinstaller --onefile --noconsole --name StopWatch stopwatch.py これでEXEファイルが作成できました! 最後に、.ps1 ファイルの2行目にある、$TargetPathをビルド結果のパスに書き換えてます。 create_shortcut.ps1 param( # ↓↓↓ この行のパスを書き換える ↓↓↓ [string]$TargetPath = "C:\Users\YourName\Documents\TIMER\dist\StopWatch.exe", [string]$ShortcutName = "StopWatch.lnk" ) # (以下は変更不要) 修正したスクリプトを実行します。 PowerShell .\create_shortcut.ps1 これで、Windowsのスタートアップフォルダにショートカットが作成されました。 PCを 再起動 してみてください。 ログイン後、自動的にストップウォッチ ( StopWatch.exe ) が起動し、デスクトップの常に一番手前に表示されれば、すべての作業は完了です。 エラー解決 PowerShellのセキュリティエラーです。 Windowsが、信頼できる作成元(Microsoftなど)によって署名されていないスクリプトの実行をデフォルトでブロックしている ために発生しています。 以下のコマンドを実行して、 今開いているこのPowerShellの画面(プロセス)だけ 、一時的にスクリプトの実行を許可します。 PowerShell Set-ExecutionPolicy Bypass -Scope Process 上記コマンドを実行した後、もう一度スクリプトを実行します。 PowerShell .\create_shortcut.ps1 振り返り:前回の開発環境 前回のストップウォッチ開発では、dev-containerを開発環境として用意していました。 dev-containerは、ホストOSから隔離されたネットワーク環境を持っています。 そのため、どこでも同じように動くクリーンな環境が出来上がります。 しかし、この「隔離」が原因で、コンテナーのGUIをPC本体の画面に映し出すために、Xサーバーの設定が必要となりました。 このように、dev-containerを使わないほうが開発が楽な場合もあると学びになりました…。 まとめ 今回は自作アプリをEXE化することと、それを使ってWindows上でアプリを自動起動させることを学んできました。 本ブログで書かれている開発コードは、私の Github に公開しているので自由にコードを書き替えて使ってみてくださいね。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post EXE化の使い方|Pythonで作ったアプリの自動起動 first appeared on SIOS Tech. Lab .
はじめに ども!Claude Codeを執筆に贅沢活用している龍ちゃんです。やっと Playwright MCP を触る機会ができました。話題になってただけあって、 めちゃくちゃ便利 ですね。 前回の記事「 Claude Code SkillでHTML図解を自動生成!時短テクニック 」で、Claude CodeにHTMLで図解を作ってもらう方法を紹介したんですが、 スクリーンショットの手間が面倒 じゃないですか。ブラウザで開いて、サイズ合わせて…って。しかも僕、DevContainer環境でブログ書いてるんで、いい感じに開けないんですよね。 そこで Playwright MCPを使ったら、さくっと実装してくれた んです。これは感動しました。 Playwright MCPは、Microsoft公式のModel Context Protocol (MCP)サーバーで、Claude CodeからPlaywrightのブラウザ自動化機能を直接呼び出せます。スクリーンショット取得はもちろん、ページ遷移、フォーム入力、要素のクリックなど、22個ものツールが使えます。 ただ、セットアップ方法が「npx版」「Docker Compose版」「Docker直接実行版」と3種類あって、 正直どれ選べばいいかわかんない ですよね。 僕自身、Node.jsが使える環境とPythonしか使えない環境でそれぞれ開発してて、「どっちにも適用したいけど、どうしよう?」って悩んだんです。そこで今回、npx版とDocker版それぞれのセットアップを検証しました。 この記事では、 環境別に最適なPlaywright MCPのセットアップ方法 を紹介します。開発環境、本番環境、DevContainer環境など、それぞれのケースでどの方式を選べばいいかを明確にしていきます。 すべての設定ファイルと詳細なREADMEは、 GitHubリポジトリ で公開しています(npx版、Docker Compose版、Docker直接実行版すべて含む)。 この記事で伝えたいこと 環境に合わせて最適なPlaywright MCPのセットアップ方法を選べるようになります。 この記事で扱う内容 : 3つのセットアップ方式(npx版、Docker Compose版、Docker直接実行版)の比較 環境別の推奨方法(開発環境、本番環境、CI/CD、DevContainer) すぐ試せるコード例(コピペ可能な設定ファイル) DevContainerでの2つの選択肢(npx vs Docker) Playwright MCPの基本 Playwright MCPとは Playwright MCPは、Microsoft Playwrightチームが公式に提供するMCPです。Claude CodeからPlaywrightのブラウザ自動化機能を直接呼び出せます。 パッケージ情報 : npm : @playwright/mcp バージョン : 0.0.47(2025年11月14日公開) ライセンス : Apache-2.0 メンテナー : Microsoft Playwright公式チーム 主な機能 Playwright MCPはコアツール20個に加え、タブ管理とブラウザインストールの計22個が標準で利用可能です。さらに、 --caps フラグでopt-inすることで、座標ベース操作、PDF生成、テストアサーション、トレーシングなど追加11個(合計33個)のツールが使えます。 本記事では、コアツールのうち以下の7個を実際に検証しました: ツール 機能 用途 browser_navigate ページ遷移 URLを開く browser_snapshot ページ構造取得 DOM情報を取得 browser_take_screenshot スクリーンショット PNG画像を保存 browser_console_messages コンソールログ取得 デバッグ情報の確認 browser_evaluate JavaScript実行 カスタムスクリプト実行 browser_install ブラウザインストール Chromiumのセットアップ 残り15個のツール (要素操作、高度な機能)は未検証ですが、公式ドキュメントによると以下のような機能があります: 要素操作: browser_click , browser_type , browser_fill_form タブ管理: browser_tabs , browser_close ファイル操作: browser_file_upload 3つのセットアップ方式 方式の比較表 項目 npx版 Docker Compose版 Docker直接実行版 Node.js必須 必要 不要 不要 Docker必須 不要 必要 必要 セットアップ時間 5分 5分(初回)、10秒(2回目以降) 中程度 設定ファイル .mcp.json のみ compose.yml + .mcp.json .mcp.json のみ ディスク使用量 約300MB 約1GB 約1GB メモリ消費 低(数百MB) 中〜高(約1GB、常駐) 低(使用時のみ) 起動速度 1-2秒 1-2秒 中程度 環境別推奨マトリクス ユースケース 推奨方式 理由 個人開発(単一プロジェクト) npx版 セットアップ簡単、高速、安定 チーム開発(開発環境) npx版 .mcp.json で共有可能 複数プロジェクト共有(開発) Docker Compose版 常駐型で複数プロジェクトから利用 本番環境 Docker直接実行版 公式推奨、セキュア、独立実行 CI/CD Docker直接実行版 クリーン環境、再現性、並列実行 DevContainer環境 npx版 stdio接続、Node.js標準搭載 方法1: npx版(開発環境推奨) 設定ファイル(コピペ可能) プロジェクトルートに .mcp.json を作成します: { "mcpServers": { "playwright": { "type": "stdio", "command": "npx", "args": [ "@playwright/mcp@latest", "--headless", "--isolated", "--browser", "chromium", "--no-sandbox" ] } } } 重要なフラグ : @latest : 常に最新版を使用(本番環境では @0.0.47 等のバージョン固定を推奨) --headless : DevContainer/Docker環境で必須(GUI表示不可能な環境) --isolated : プロファイルロック問題を回避( 必須フラグ ) --browser chromium : ブラウザを明示的に指定 --no-sandbox : DevContainer/Docker環境で必須 セキュリティ警告 : --no-sandbox フラグはChromiumのサンドボックス保護を無効化します。DevContainer/Docker環境では必須ですが、本番環境での使用は慎重に検討してください。 セットアップ手順(5分) Step 1 : 上記の .mcp.json をプロジェクトルートに作成 Step 2 : VSCodeをリロード Cmd/Ctrl + Shift + P → “Developer: Reload Window” Step 3 : Chromiumをインストール npx playwright install chromium ダウンロードサイズ: 約174MB 所要時間: 約30秒 Step 4 : 動作確認 Claude Codeで以下のように依頼します: Playwright MCPを使用して、https://example.com を開いてページタイトルを取得してください 期待される結果 : ページURL: https://example.com ページタイトル: “Example Domain” エラーなし メリット・デメリット メリット(開発環境) : インストール不要 – npx経由で即座に実行 公式サポート – Microsoft公式チームがメンテナンス 最新版自動取得 – @latest で常に最新 高速・軽量 – 1-2秒で起動(開発環境で検証済み) チーム共有簡単 – .mcp.json をGit管理 構造化アプローチ – アクセシビリティツリー使用 デメリット・制約 : 開発環境向け – 本番環境での使用は未検証 初回起動遅い – パッケージダウンロード(数秒〜数十秒) ネットワーク依存 – インターネット接続必要(初回/ @latest 使用時) Node.js必須 – Node.js v20以上が必要 キャッシュ管理 – npm cacheに約300MB消費 推奨ケース npx版が最適 : 個人開発(単一プロジェクト) チーム開発( .mcp.json 共有) DevContainer環境 頻繁な使用(開発中) プロトタイピング・検証 npx版を本番環境で使用する場合の推奨事項 : 本記事では主に開発環境での使用を検証していますが、本番環境で使用する場合は以下の対策を推奨します: バージョン固定 : @latest ではなく @0.0.47 等の具体的なバージョンを指定 十分な検証 : 負荷テスト・セキュリティ検証を実施 監視体制 : エラーハンドリング・監視体制を構築 障害対策 : ネットワーク障害時の挙動を確認 より安全な本番環境運用には、Docker直接実行版の検討もご検討ください(セキュリティ重視、クリーン環境)。 方法2: Docker Compose版(常駐型・開発環境向け) compose.yml(コピペ可能) プロジェクトルートに compose.yml を作成します: services: playwright-mcp: image: mcr.microsoft.com/playwright:v1.49.1-noble container_name: playwright-mcp-server ports: - "8931:8931" environment: - PLAYWRIGHT_BROWSERS_PATH=/ms-playwright - PLAYWRIGHT_CHROMIUM_ARGS=--no-sandbox --disable-setuid-sandbox command: > sh -c " npx playwright install chrome && npm install -g @playwright/mcp@latest && npx @playwright/mcp@latest --port 8931 --headless --isolated --no-sandbox " restart: unless-stopped networks: - mcp-network networks: mcp-network: name: mcp-network driver: bridge .mcp.json(コピペ可能) { "mcpServers": { "playwright": { "command": "docker", "args": [ "exec", "-i", "playwright-mcp-server", "node", "/root/.npm/_npx/9833c18b2d85bc59/node_modules/.bin/mcp-server-playwright", "--isolated", "--no-sandbox" ] } } } 注意 : npxのパス( /root/.npm/_npx/... )は環境により異なる場合があります。 パスの確認方法 : docker exec -it playwright-mcp-server bash find /root/.npm/_npx -name "mcp-server-playwright" パスが異なる場合は、 .mcp.json の該当箇所を更新してください。 セットアップ手順 Step 1 : 上記の compose.yml をプロジェクトルートに作成 Step 2 : サーバー起動 docker compose up -d 初回: 約5分(イメージ743MB + Chrome 112MB) 2回目以降: 約10秒 Step 3 : 上記の .mcp.json を作成(npxパスを確認) Step 4 : VSCodeをリロード メリット・デメリット メリット : 複数プロジェクト共有 – 常駐型で複数から利用可能 環境分離 – Dockerコンテナで独立 自動再起動 – restart: unless-stopped 管理が簡単 – Docker Composeで一元管理 stdio接続 – docker exec経由で安定した通信 デメリット : 初回起動時間 – 約5分(イメージ743MB + Chrome 112MB) リソース常時消費 – メモリ・CPU常駐(約1GB) npxパス依存 – パスが環境により異なる可能性 Docker知識必要 – Docker/Docker Composeの理解が必要 推奨ケース Docker Compose版が適している場合 : 複数のプロジェクトで共有したい 開発環境での頻繁な使用 チーム全体で統一環境を使用したい リソースを常時確保できる環境がある npx版が適している場合 : 単一プロジェクトでのみ使用 リソース消費を最小限に抑えたい Docker環境を構築したくない 安定したパフォーマンスが必要 方法3: Docker直接実行版(都度起動型・本番環境推奨) .mcp.json(コピペ可能) { "mcpServers": { "playwright": { "command": "docker", "args": [ "run", "-i", "--rm", "--init", "--pull=always", "mcr.microsoft.com/playwright/mcp", "--isolated" ] } } } 特徴とメリット 特徴 : 公式イメージ : mcr.microsoft.com/playwright/mcp 実行方式 : docker run --rm (終了後自動削除) セッション毎に新しいコンテナ : 完全に独立 公式ドキュメントで紹介 : セキュリティ重視の場合に適した方式 メリット : 最もセキュア – セッション毎に独立 リソース効率的 – 使用時のみ起動 常に最新 – --pull=always で最新イメージ クリーン – --rm で自動削除 本番環境向け設計 推奨ケース Docker直接実行版が適している場合 : 本番環境 – セキュリティ重視 CI/CD環境 – クリーンな環境、再現性 各実行が独立が必要 – テストの独立性 リソース効率重視 – 使用時のみリソース消費 常に最新版を使用 – 自動更新が必要 他の方式が適している場合 : npx版 – Node.js環境があり、高速起動が必要(開発環境) Docker Compose版 – 複数プロジェクトで共有、常駐型が必要(開発環境) コラム:DevContainerでの選択 DevContainer環境でPlaywright MCPを使う場合、2つの選択肢があります。僕自身、最初はどちらを選べばいいか迷ったんですが、実際に両方試してみて分かったことをシェアします。 選択肢1: npx版をコンテナ内に収める 設定例 ( .mcp.json ): { "mcpServers": { "playwright": { "type": "stdio", "command": "npx", "args": [ "@playwright/mcp@latest", "--headless", "--isolated", "--no-sandbox" ] } } } メリット : シンプル – DevContainerにはNode.js標準搭載 高速 – ネットワーク経由不要、stdio接続 設定が簡単 – .mcp.json のみ デメリット : Node.js必須 – DevContainerにNode.jsが必要 コンテナサイズ増加 – npm cache約300MB 選択肢2: Docker版をホストで動かす 設定例 (Docker Compose版の場合): DevContainerの devcontainer.json でホストDockerソケットを共有: { "mounts": [ "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" ] } .mcp.json は「方法2: Docker Compose版」と同じ。 メリット : Node.js不要 – DevContainerにNode.jsが不要 リソース分離 – ホスト側でブラウザ実行 デメリット : Docker socket共有が必要 – セキュリティ考慮が必要 設定が複雑 – devcontainer.json の編集が必要 ネットワーク経由 – やや遅延が発生する可能性 どちらを選ぶか 僕の推奨: npx版をコンテナ内に収める 理由は以下の3つです: DevContainerにはNode.js標準搭載 わざわざDockerソケット共有の設定をする必要がない 高速で安定 stdio接続なので、ネットワーク経由の遅延がない シンプル .mcp.json だけで完結 Docker版が必要なケース : Node.jsを使わないプロジェクト(Python専用など) リソースを完全に分離したい 複数のDevContainerプロジェクトで共有したい 実際の使い方 Claude Codeでの基本操作 セットアップが完了したら、Claude Codeで以下のように依頼するだけで使えます: 例1: ページを開いてスクリーンショット Playwright MCPを使って、https://playwright.dev を開いて、スクリーンショットを撮影してください 例2: ページタイトルを取得 Playwright MCPで https://example.com のページタイトルを取得してください パフォーマンス・動作確認データ(参考) 動作確認(npx版、開発環境で検証) : 操作 時間 結果 ブラウザ起動(初回) 1-2秒 ブラウザ起動(2回目以降) < 1秒 example.com ナビゲーション < 1秒 playwright.dev ナビゲーション < 2秒 スクリーンショット取得 < 1秒 3つの方式のパフォーマンス比較 : 操作 npx版 Docker Compose版 ブラウザ起動 1-2秒 1-2秒 ページアクセス < 1秒 27-94秒(ばらつき大) スクリーンショット < 1秒 < 1秒 初回セットアップ 約30秒 約5分 結論 : 実用上は大きな差はありませんが、 npx版の方が安定している 印象です。Docker Compose版はページアクセスにばらつきがあるので、開発環境で頻繁に使うならnpx版がおすすめです。 驚くほど高速でした。 特にnpx版は、開発環境での使用であれば非常に安定しています。 トラブルシューティング 問題1: プロファイルロックエラー エラーメッセージ : Error: Browser is already in use for /home/node/.cache/ms-playwright/mcp-chrome-* use --isolated to run multiple instances of the same browser 解決策 : .mcp.json に --isolated フラグを追加 VSCodeをリロード 予防策 : 最初から --isolated を含める(強く推奨) 問題2: MCPサーバーが認識されない 解決策 : .mcp.json の構文確認(JSONバリデーター使用) VSCodeをリロード Claude CodeのOutputパネルでエラーログ確認 問題3: Chromiumが起動しない 解決策 : npx playwright install chromium Chromiumがインストールされていない場合は、上記コマンドで手動インストールしてください。 問題4: Docker Compose版でnpxパスが見つからない 解決策 : docker exec -it playwright-mcp-server bash find /root/.npm/_npx -name "mcp-server-playwright" パスを確認して、 .mcp.json を更新してください。 まとめ 今回は、Playwright MCPの環境別セットアップ方法を紹介しました。 環境別の選択ガイド 開発環境(個人・チーム) : npx版 セットアップ簡単(5分) .mcp.json だけで完結 高速・安定 開発環境(複数プロジェクト) : Docker Compose版 常駐型で複数から利用 環境分離 本番環境/CI/CD : Docker直接実行版 公式推奨 セキュア クリーン環境 DevContainer環境 : npx版 Node.js標準搭載 stdio接続で高速 この記事で実現できたこと 環境に合わせた最適なセットアップ方法の選択 コピペで試せる設定ファイル DevContainerでの選択肢(npx vs Docker) トラブルシューティング より詳しく知りたい方へ : すべての設定ファイルと詳細なREADMEは、 GitHubリポジトリ で公開しています(npx版、Docker Compose版、Docker直接実行版すべて含む)。 次のステップ 前回の記事「 Claude Code SkillでHTML図解を自動生成!時短テクニック 」で紹介したHTML図解の作成と、今回のPlaywright MCPセットアップを組み合わせることで、 HTML→PNG変換の完全なワークフロー が実現できます。 次回は、この HTML→PNG変換の詳細 について解説する予定です。Playwright MCPを使った自動スクリーンショット取得、画像最適化、ブログへの埋め込みまでの一連の流れを紹介します。 皆さんも、ぜひPlaywright MCPでブラウザ自動化にチャレンジしてみてください!質問や感想は、コメント欄でお待ちしております。 参考リンク 公式ドキュメント Playwright MCP GitHub npm パッケージ Playwright公式サイト MCP仕様 前提記事 Claude Code SkillでHTML図解を自動生成!時短テクニック HTML図解の自動生成方法 Tailwind CSS + Material Iconsの活用 PNG変換の基本 GitHubリポジトリ playwright-mcp-sample 3つのセットアップ方法の完全なサンプルコード DevContainer対応 すべて動作検証済み 詳細なREADME(日本語) MITライセンス 次に読むべき記事 HTML→PNG変換の詳細 (次回予定) Playwright MCPを使った自動スクリーンショット 画像最適化のベストプラクティス ブログへの埋め込みワークフロー 最後まで読んでいただき、ありがとうございました! この記事が役に立ったら、ぜひSNSでシェアしてください。質問やフィードバックは、 @RyuReina_Tech や @SIOSTechLab でお待ちしています! ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Playwright MCPで始めるブラウザ自動化|環境別セットアップガイド first appeared on SIOS Tech. Lab .
はじめに:指示をさぼりたい どうも、Claude Codeとべったりな龍ちゃんです。 最近、Claude Codeが選択肢式の出力を出してきて、質問に答えたらいい感じに指示を分類してくれたりしてたんですよ。調べたら、どうやら9月ぐらいに発表された機能らしくて。 「これ毎回発火してくんねーかな」 って思ったんですよね。 AI使うことでだいぶ楽になったんですけど、人間って怠惰なんで。指示をちゃんと打ち込めば動くのはわかってるんですけど、エージェント発火させたりスキル発火させたりするのを すげえさぼりてえな って。 僕、今 ブログのエージェント を何個か作っていて、タイトルやメタディスクリプションを作ったり、ブログのレビューとか技術情報収集とか、いろんなエージェントがあるんですけど。それぞれ一個ずつ発火させるのって クソ面倒臭い ですよね。 それが選択肢式で、「選択肢出して」って言ったら出してくれて、ぼちぼち設定できたら いいな って思って、こんなブログを書いてます。 で、調べてわかったことなんですけど、 全然失敗することもある らしいんですよね。僕の環境でもめちゃくちゃ失敗してるんで、まあ今後に期待したいみたいな話で、ちょっと先んじて書いておこうかなって思ってます。 注意点としては : まだまだ開発中というか、品質として良いとは言えない状態 すぐ取り込むのは良くないんじゃないかな 発火したらラッキーと思ってるぐらいがちょうどいい この画面、見たことありますか? Claude Codeが質問してくれるやつです。 でも現実は… これを確定で発火させて、Skillsとして提供しておいて、どのエージェント発火するかをCLI的に選ぼうみたいな とち狂ったこと を書いていきます。 具体的にどうするのかと、このツールのちょっと参考になる情報を、さっくりまとめていこうかなと思ってます。もしもあれなら参考にしてもらえればなと。 AskUserQuestionツールって何? AskUserQuestion は、タスク実行中に対話的な質問をするためのツールです。 (2025年11月時点のClaude Code v2.0.46で動作確認済み) 理想的な動作: ユーザーに選択肢を提示 ユーザーが選択(単一または複数) 回答を受け取って処理を分岐 実装例: AskUserQuestion({ questions: [ { question: "この記事の現在の状態を教えてください", header: "記事の状態", multiSelect: false, options: [ { label: "初稿完成(技術チェック必要)", description: "書き上げたばかりで、技術的正確性とセキュリティを確認したい" }, // ... 他の選択肢 ] } ] }) 詳しい作り方は Claude Codeに聞いてみて! (どうせ今後変わるかもしれないし) 現実:めちゃくちゃ失敗する 調査したところ、 AskUserQuestion は現状かなり不安定 でした。 既知の問題: ✗ 公式ドキュメントに包括的な説明なし ✗ スキル内で初回呼び出し時に失敗 ✗ “User answered Claude’s questions:” と表示されるが実際には質問しない ✗ 空の応答で処理が完了してしまう △ プランモード切り替えで一時的に機能することがある(不安定) GitHubイシュー: #9846: AskUserQuestion tool doesn’t work in skill until plan mode toggled #9912: Can’t trigger AskUserQuestion tool #9854: Related duplicate issues ツールが発火しなかった時にどうするか その時はまあ、サボらず、ちゃんとプロンプトを打ち込もうな って話ですね。 ちゃんと動かしたら、エージェントとかSkillsとか出てきて、だいぶ言うこと聞いてくれるようになったり、作業が自動化されたりしてるんで。その辺ね、多少プロンプトサボっちゃダメですよ。 回避策 SkillsとかAgentがちゃんと発火しないとき: description でどうにかする CLAUDE.md にちゃんと説明を書く 例えば、 CLAUDE.md にこんな感じで書いておく: **⚠ レビュー依頼の処理方法**: ユーザーが記事のレビューを依頼した場合(「レビューして」「チェックして」「確認して」など)、 以下のエージェントを**直接呼び出さず**、必ず`.claude/skills/review-article.md`スキルを発火させてください: - blog-reviewer - content-reviewer - technical-accuracy-reviewer - seo-title-generator review-articleスキルがユーザーの意図を確認し、適切なエージェントを選択します。 こういうことで、まあ大体はできるので。 僕の実装例:review-article.md スキル 参考までに、僕が作った review-article.md スキルを紹介します。 やりたいこと: 「この記事をレビューして」だけで、適切なエージェントを選びたい 4つのエージェント(技術チェック、品質改善、SEO、タイトル生成)を使い分けたい 理想的な動作: AskUserQuestion で記事の状態を質問 どのレビュー項目を実行するか選択(複数選択可) 選択に基づいて適切なエージェントを順次実行 現実: AskUserQuestionが動かない でもキーワードトリガー(「レビューして」など)は動く CLAUDE.mdで制御すれば、まあまあ使える 詳しい実装は Claude Codeに聞いてみて! (長いので) まとめ 「Claude Codeへの指示を少しでもさぼりたい」という正当な欲求から生まれた実験。 現状: AskUserQuestionは不安定 でも将来的には期待できそう 今は代替策でなんとかする 推奨: キーワードトリガーを活用 CLAUDE.mdで制御 ちゃんとプロンプトを打ち込む ✗ AskUserQuestionに依存しない 学び: スキル・エージェント連携の実装パターンは参考になる フォールバック戦略は重要 発火したらラッキー、ぐらいの気持ちで 「さぼりたい」という気持ちは、エンジニアリングの原動力です。理想と現実のギャップを理解しつつ、現実的な代替策で効率化を追求していきましょう。 ぜひ面白コンテンツだと思って読んでもらえればなと思います。 参考リンク 公式ドキュメント: Claude Code CLI Reference – Anthropic Docs Claude Code GitHub Repository 既知の問題: #9846: AskUserQuestion tool doesn’t work in skill until plan mode toggled #9912: Can’t trigger AskUserQuestion tool #9854: Related duplicate issues ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Claude Codeへの指示を少しでもさぼりたい!AskUserQuestionツール first appeared on SIOS Tech. Lab .
この記事では、AzureMCPServerとStreamlitを組み合わせて、Azureリソースを対話的に操作するWebアプリケーションを構築する方法について説明します。 つまり以下のように「Azureのコレコレのリソースの情報取得して」とか「Azure Blob Storageのコンテナ作って」みたいにWebブラウザから対話的に指示すると、そのとおりにAzureリソースが出来上がるWebアプリをサクッと作ってしまおうという感じです。 説明はいいからサクッと動かしたいよーという方はソースコードと起動方法を以下のGitリポジトリで公開しているので、そちらを参照してください。 https://github.com/noriyukitakei/azure-mcp-server-webif Azure MCP Serverとは? Azure MCP Serverとは、Azureが提供しているMCPサーバーであり、Azureリソースの管理や操作を行うための機能を提供します。 https://learn.microsoft.com/ja-jp/azure/developer/azure-mcp-server/tools/ MCP(Model Context Protocl)に準拠しているので、MCPに対応しているクライアントであれば、Visual Studio CodeやCursor、Eclipse、IntelliJなど、様々な開発環境からAzureリソースを操作することができます。 今回構築するWebアプリケーションについて Visual Studio Code などから Azure MCP Server と連携する例は多く紹介されていますが、本記事では Streamlit を使って Web インターフェースを構築し、Azure MCP Server と連携する方法 を紹介します。これにより、ブラウザ上から Azure リソースを対話的に操作できるようになり、より多くのユーザーにとって使いやすいインターフェースを提供できます。 ただし、適切な権限管理を行わないと、意図しない Azure リソースの変更が発生する可能性があるため注意してください。 今回構築するアプリのソースコードは以下のGitHubリポジトリで公開しています。 https://github.com/noriyukitakei/azure-mcp-server-webif.git 構成 今回構築するシステムの構成は以下の通りです。 UIを提供するStreamlit、LLMによる思考を担うAIエージェント、MCPクライアント、Azure MCP Serverの4つのコンポーネントで構成されます。UI、AIエージェント、MCPクライアントは同一のWebアプリケーション(プロセス)内で動作し、Azure MCP Serverとの通信方式はSTDIO(標準入出力)を使用します。 UI Webアプリケーションのユーザーインターフェース部分です。Streamlitを使用して構築します。ユーザーからの入力を受け取り、結果を表示します。 Streamlitは、Pythonを使って簡単にインタラクティブなWebアプリケーションを作成できるオープンソースのフレームワークです。プログラミングの経験が少なくても、Pythonコードを書くだけで、データビジュアライゼーションやインターフェースを持つアプリをすぐに作ることができるのが特徴です。 従来、Webアプリケーションを作成するには、フロントエンド(HTML、CSS、JavaScript)とバックエンド(Python、Django、Flaskなど)の両方の技術を理解する必要がありました。しかし、Streamlitを使えば、Pythonだけでフロントエンドとバックエンドを同時に構築できるため、非常に手軽にアプリ開発に取り組めます。 たとえば、データサイエンティストがモデルの結果を共有したり、エンジニアがプロトタイプを素早く作成したりする場面でよく利用されています。 AIエージェント ユーザーからの指示を受け取り、適切なアクションを判断し、必要に応じてMCPサーバーにリクエストを送信します。 Function Callingを活用し、AIエージェントの思考と行動を実現します。Function Callingに対応したLLMを使用する必要があるため、今回は Azure OpenAI Serviceを利用しますが、他の対応LLMに置き換えることも可能です。 なお、AIエージェントは LangChainのようなAIエージェントフレームワークを用いて実装することもできます。しかし今回は学習を目的として、できるだけシンプルな独自実装で進めます。そのため、コードはやや冗長であり、実際のアプリケーションで使用するには最適化が必要な部分もありますが、基本的な仕組みを理解するには十分な内容になっています。 MCPクライアント MCPクライアントは、FastMCPを用いて実装しています。FastMCP は、MCPサーバーとMCPクライアントの両方の機能を提供するライブラリであり、ここではMCPクライアントとして使用します。 MCPサーバー Azure MCP Server本体になります。Azureリソースの管理や操作を行うための機能を提供します。npxやnpm、Dockerで起動する方法がありますが、今回はDockerで起動し、通信方式はSTDIO(標準入出力)を使用します。 処理の流れ 今回構築するWebアプリケーションの処理の流れは以下の通りです。 [ステップ1] ユーザーが指示を入力 ユーザーはWebアプリケーションのUIを通じて、Azureリソースに対する操作指示を入力します。例えば「ストレージ アカウント ‘ntakeiassets’ のコンテナー ‘images’ の ‘log4j.png’ の詳細を教えて」と入力するとします。 その指示は、StreamlitによるUIを通じてAIエージェントに送信されます。 [ステップ2] MCPサーバーへの初期化要求 MCPクライアントは、initializeというメソッドで初期化メッセージを最初に送ります。これは、MCPクライアントがMCPサーバーに対して「自分の機能・情報・バージョンなどを伝えて、接続を初期化したい」とリクエストしているメッセージです。 [ステップ3] MCPサーバーからの初期化応答 MCPサーバーはinitializeリクエストを受け取り、初期化応答を返して、自身のプロトコルのバージョンなどをMCPクライアントに伝えます。 [ステップ4] 初期化完了通知の送信 MCPクライアントは、MCPサーバーからの初期化応答を受け取り、初期化が完了したことをMCPサーバーに通知します。 [ステップ5] ツールの一覧取得 MCPクライアントは、tools/listというメソッドでツールの一覧(そのMCPサーバーが持っている機能の一覧)をMCPサーバーにリクエストします。これにより、MCPサーバーが提供するツールの情報を取得します。 [ステップ6] ツール一覧の応答受信 MCPサーバーは、tools/listリクエストを受け取り、提供するツールの一覧をMCPクライアントに返します。ここではAzure MCP Serverが提供するツールの一覧(Azure Blob StorageやAzure AI Searchなどのリソースを操作するコマンド一覧)が返されます。 [ステップ7] LLMへのFunction Calling指示 AIエージェントは、MCPクライアントから渡されたツール一覧をもとに、LLMに対してFunction Callingを行うよう指示します。具体的には、ユーザーからのプロンプトを解析してどのツールを呼び出すべきかを判断し、そのツールを使うようLLMに指示します。 ここでは、ユーザーの質問である「ストレージ アカウント ‘ntakeiassets’ のコンテナー ‘images’ の ‘log4j.png’ の詳細を教えて」とともに、tools/listで取得したツール一覧をLLMに渡します。 [ステップ8] LLMからの関数呼び出し応答 LLMは、AIエージェントからのFunction Calling指示を受け取り、適切な関数呼び出し応答を生成します。この応答には、呼び出す関数名とそのパラメータが含まれます。 ここでは、sotorageというツールをLLMが選択したことがわかります。これはAzure Blob Storageの情報を取得するためのツールであり、ユーザーの質問に対して適切な選択となります。 [ステップ9] MCPサーバーへの関数呼び出しリクエスト AIエージェントはLLMからの関数呼び出し応答を受け取り、MCPクライアントを介してMCPサーバーに関数呼び出しリクエストを送信します。これにより、MCPサーバーに対して指定された関数を実行させます。 [ステップ10] MCPサーバーからの関数呼び出し応答 MCPサーバーは、MCPクライアントからの関数呼び出しリクエストを受け取り、指定された関数を実行します。その結果をMCPクライアントに返します。 今回は、Azure Blob Storageのさらに細かいコマンド一覧が返されています。 つまり、1回目のツール一覧取得では大まかなツール一覧が返され、2回目の関数呼び出し応答では、さらに詳細なコマンド一覧が返される形となっています。 [ステップ11] LLMへの追加Function Calling指示 ステップ11で取得した詳細なコマンド一覧をもとに、AIエージェントはLLMに対して追加のFunction Callingを行うよう指示します。これにより、ユーザーの質問に対してさらに具体的な回答を生成するための情報を提供します。 [ステップ12] LLMからの関数呼び出し応答 LLMは、AIエージェントからの追加Function Calling指示を受け取り、適切な関数呼び出し応答を生成します。この応答には、呼び出す関数名とそのパラメータが含まれます。 以下のような応答が返され、Azure Blob Storageの特定のコンテナ内にあるファイルの詳細情報を取得するための関数呼び出しが示されています。 "function_call": { "name": ”storage_blob_get", "arguments": "{'account': 'ntakeiassets', 'container': 'images', 'blob': 'log4j.png'}" } つまりこれは、storage_blob_getというコマンドを用いて、ストレージアカウント ‘ntakeiassets’ のコンテナ ‘images’ 内の ‘log4j.png’ というファイルの詳細情報を取得するための関数呼び出しを意味しています。 [ステップ13] MCPサーバーへの関数呼び出しリクエスト AIエージェントはLLMからの関数呼び出し応答を受け取り、MCPクライアントを介してMCPサーバーに関数呼び出しリクエストを送信します。これにより、MCPサーバーに対して指定された関数を実行させます。 [ステップ14] Azure Resource ManagerへのAPIリクエスト MCPサーバーは、MCPクライアントからの関数呼び出しリクエストを受け取り、そのコマンドをAzure Resource Manager (ARM) へのAPIリクエストに変換して実行します。これにより、Azureリソースに対する操作が行われます。 [ステップ15] MCPサーバーからの関数呼び出し応答 MCPサーバーは、Azure Resource ManagerからのAPIレスポンスを受け取り、その結果をMCPクライアントに返します。 今回は、指定されたストレージアカウント、コンテナ、ファイルに関する詳細情報が返されます。これには、ファイルのサイズ、作成日時、更新日時、コンテンツタイプなどのメタデータが含まれています。 [ステップ16] LLMへの最終Function Calling指示 AIエージェントはMCPクライアントからの関数呼び出し応答を受け取り、LLMに対して最終的なFunction Callingを行うよう指示します。これにより、ユーザーの質問に対する最終的な回答を生成するための情報を提供します。 [ステップ17] LLMからの最終応答 LLMは、AIエージェントからの最終Function Calling指示を受け取り、ユーザーの質問に対する最終的な応答を生成します。この応答には、Azureリソースに関する詳細情報が含まれています。 そして、AIエージェントはこの最終応答をWebアプリケーションのUIに返します。 起動方法 処理の流れをご理解いただけたところで、実際にアプリケーションを起動して動作させてみましょう。以下の手順で進めてください。 [ステップ1] リポジトリのクローン まず、GitHubリポジトリをクローンします。ターミナルを開き、以下のコマンドを実行してください。 $ git clone https://github.com/your-repository-url.git $ cd your-repository-directory [ステップ2] 環境変数の設定 次に、必要な環境変数を設定します。 `.env.example` ファイルをコピーして `.env` ファイルを作成し、必要な値を設定してください。 $ cp .env.example .env .env ファイル内で設定する主な環境変数は以下の通りです。 AZURE_OPENAI_ENDPOINT : Azure OpenAI ServiceのエンドポイントURL AZURE_OPENAI_API_KEY : Azure OpenAI ServiceのAPIキー AZURE_OPENAI_API_VERSION : 使用するAPIバージョン (例: 2024-06-01) AZURE_OPENAI_CHAT_DEPLOYMENT : 使用するチャットモデルのデプロイメント名 (例: gpt-4)` MAX_STEPS : AIエージェントが実行する最大ステップ数 (例: 5) AZURE_TENANT_ID : AzureテナントID AZURE_SUBSCRIPTION_ID : AzureサブスクリプションID AZURE_CLIENT_ID : AzureクライアントID AZURE_CLIENT_SECRET : Azureクライアントシークレット AZURE_OPENAI_ENDPOINT 、 AZURE_OPENAI_API_KEY 、 AZURE_OPENAI_CHAT_DEPLOYMENT は、Azure OpenAI Serviceに接続するための情報となります。これはLLMにFunction Callingを実行させるために必要です。 AZURE_TENANT_ID 、 AZURE_SUBSCRIPTION_ID 、 AZURE_CLIENT_ID 、 AZURE_CLIENT_SECRET は、Azure MCP ServerがAzureリソースにアクセスするための情報となります。これらの値はAzureポータルでアプリケーション登録を行い、サービスプリンシパルを作成することで取得できます。そして、そのサービスプリンシパルに対して必要なAzureリソースへのアクセス権限を付与してください。例えば、ストレージアカウントの情報を取得する場合は、「ストレージ アカウント閲覧者」ロールを付与します。 MAX_STEPS は、AIエージェントが実行する最大ステップ数を指定します。これにより、無限ループを防止できます。もしこれを設定しないと、AIエージェントが過剰に多くのステップを実行し、Azure OpenAI Serviceにすごいい数のリクエストを送ってしまう可能性があります。結果、コストが高額になる恐れがあるため、適切な値を設定してください。 [ステップ3] 依存関係のインストール 次に、必要なPythonパッケージをインストールします。以下のコマンドを実行してください。 $ pip install -r requirements.txt [ステップ4] アプリケーションの起動 ブラウザで http://localhost:8501 にアクセスし、Azureリソースに対する操作指示を入力してみてください。例えば、「ストレージ アカウント ‘ntakeiassets’ のコンテナー ‘images’ の ‘log4j.png’ の詳細を教えて」と入力すると、アプリケーションがAzure MCP Serverと連携して情報を取得し、結果を表示します。 まとめ いかがでしょうか。Webブラウザから対話的にAzureリソースを操作できるのは非常に便利です。Azure MCP ServerとStreamlitを組み合わせることで、ユーザーにとって使いやすいインターフェースを提供できます。こんな感じで今後も、Azureの様々なサービスと連携したWebアプリケーションを構築していきたいと思います。ぜひ皆さんも試してみてください。 ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post Azure MCP ServerとStreamlitでAzureを対話的に操作するWebアプリ first appeared on SIOS Tech. Lab .
はじめに 前回はKubernetesにおけるデータ永続化について解説しました。 今回は、実際にKubernetesのデータ永続化機能を利用してKubernetes上でDBコンテナを起動する方法をハンズオン形式で紹介します。 今回の構成 以下の図1は、今回のハンズオンで作成するKubernetesでMySQLのようなデータベースを安定して動かすための仕組みを表しています。 図1:StatefulSetで構成されたMySQLコンテナの概念図 前提条件 kubectlが使用可能である minikubeがインストール済み バージョン:v1.36.0 使用するMySQLコンテナ イメージ:MySQL:8.0 事前準備 今回のハンズオンで使用するsample_mysql.ymlを以下に記載します。 apiVersion: v1 kind: Service metadata: name: mysql-service labels: app: mysql spec: ports: - port: 3306 name: mysql clusterIP: None selector: app: mysql --- apiVersion: v1 kind: Secret metadata: name: mysql-secret type: Opaque stringData: mysql-root-password: "mysql_root_password" --- apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql-statefulset spec: serviceName: "mysql-service" replicas: 1 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:8.0 env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-secret key: mysql-root-password volumeMounts: - name: mysql-persistent-storage mountPath: /var/lib/mysql volumeClaimTemplates: - metadata: name: mysql-persistent-storage spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "standard" resources: requests: storage: 1Gi 主要なパラメーター sample_mysql.yml内の主要なパラメーターについて説明します。 kind: Service Kubernetesにおいてネットワークサービスを定義するためのオブジェクトです。今回のファイルではmysqlというラベルがついたPodをサービスの管理対象とすると指定しています。 kind: Secret パスワードなどの機密情報を安全に格納し、Podに環境変数として渡すために使用されるKubernetesリソースであるSecretを設定します。今回のファイルではmysqlのパスワードなどを格納しています。 kind: StatefulSet ステートフルなアプリケーションのデプロイと管理を行うために使用されるKubernetesリソースであるStatefulSetを設定します。StatefulSetはPodに固有の識別子を与えたり、安定したストレージを保証する設定を行うことでDBコンテナ運用において重要な役割を果たしています。 volumeClaimTemplates Podごとに永続ボリューム要求(PVC)を動的に作成するためのテンプレートを定義する、StatefulSetに特有のフィールドです。今回はこのフィールドで永続ストレージを確保するための設定をしています。 metadataはPVCの「名前」などのメタデータを定義します。 今回は『name: mysql-persistent-storage』で名前を定義しています。 specでは仕様の定義を行います。 accessModes: [ “ReadWriteOnce” ]ではアクセスモードを指定します。ReadWriteOnceは1つのノードからの読み書き可能という仕様の設定です。 storageClassName: ストレージクラスとは、Kubernetesでストレージの種類や動作を指定するための設定テンプレートです。今回はストレージのクラスをstandardに設定します。 resourcesのstorage: 1Giではストレージの容量として1Giを要求しています。 Kubernetes上でMySQLコンテナを起動 StatefulSetを利用してMySQLコンテナをminikube上にデプロイ minikube startコマンドを実行し、minikubeを起動します。 minikube start minikubeの起動 kubectl applyはYAMLやJSONなどの設定ファイルをKubernetesクラスターに適用し、リソースの状態を管理するためのコマンドです。このコマンドを使用してsample_mysql.ymlをKubernetesクラスターに適用します。 kubectl apply -f "sample_mysql.yml" 設定ファイルの適用 Podと永続ボリューム(PV/PVC)の状態を確認 kubectl getコマンドはKubernetesクラスター内のリソースの一覧を取得するコマンドです。このコマンドを使用することで、Pod、PVC(PersistentVolumeClaim)、PV(PersistentVolume)の状態を確認できます。 kubectl get pods を実行することで、Podの一覧とそれぞれのステータスを確認できます。`STATUS`の個所にRunningと表示されていれば正常に稼働していることを示します。 kubectl get statefulsetsを実行することで、StatefulSetが正常に動作しているか確認できます。特に`READY`の値が期待される数と一致している場合正常に動作していると確認できます。 kubectl get pvcとkubectl get pvを実行することで、PVCとPVの状態を確認できます。PVCとPVがBound状態であれば、ストレージが正常に割り当てられていることを示します。また、`CLAIM`フィールドには対応するPVCやPVの名前が記載されており、どのリソースがストレージを利用しているかを確認できます。さらにStatefulSetではvolumeClaimTemplatesによってPodごとに固有のPVCが作成され、専用のPVと1対1で紐づくことにより各Podが専用の永続ストレージを持つことができます。 kubectl get pods kubectl get statefulsets kubectl get pvc kubectl get pv Kubernetesクラスター内のpodの状態確認 SratefulSetの状態確認 PVCの状態確認 PVの状態確認 データが永続化されていることを確認 データの永続化が正しく機能しているか確認するために今回はMySQLコンテナ内に新しいデータベースを作成します。 kubectl exec -it "kubectl get podsで取得したpod名" -- mysql -uroot -p CREATE DATABASE "任意のデータベース名"; 初期状態のデータベース 新しいデータベースを作成 次に、Podを削除して再作成される様子を確認します。この手順では、Podが削除されてもストレージ永続化の仕組みによってデータが保持されていることを検証します。StatefulSetではPodが削除されても同じ名前のPodが再作成され、PVCやPVもそのPodに紐づいた状態を維持します。 kubectl delete pod "pod名" podの削除と再作成の確認 Podは削除すると自動で再作成されます。Podの再作成後MySQLコンテナ内に入り、作成したデータベースが残っているかを確認します。データベースが残っていたらKubernetesのストレージ永続化が正しく機能しています。 データの永続化の確認 おわりに 今回はハンズオンを通して、StatefulSetとPV/PVCの利用により、コンテナ環境で安全にDBを運用する方法を紹介しました。 次回はKubernetes上のアプリケーションコンテナがDBコンテナに接続する仕組みについて解説します。 参考文献 https://kubernetes.io/docs/concepts/services-networking/service/ https://kubernetes.io/docs/concepts/services-networking/service/#headless-services https://kubernetes.io/docs/concepts/configuration/secret/ https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/ https://kubernetes.io/docs/reference/kubectl/generated/kubectl_apply/ ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post コンテナDB実践シリーズ③:Kubernetesでデータベースを動かしてみた first appeared on SIOS Tech. Lab .