ASP.NETアプリケーションのモダナイズインフラ編
はじめに
.NETラボ勉強会2025年4月にて、ASP.NETアプリケーションのモダナイゼーションについてアプリケーション側のお話をしました。本記事では、Webアプリケーションを動作させる基盤(インフラ)側の考慮にフォーカスし、アプリケーション開発側の立場でどのようにサービスをセレクトしていけばいいのか、思考過程を交えてお話しします。🚀
モダナイゼーションとは?
モダナイゼーションとは、老朽化した既存システムを現在のニーズに合うように刷新することです。
本記事では、.NET Frameworkで構築されたシステムを.NETベースに刷新し、必要に応じてUIを刷新することを指します。具体的には以下のようなターゲットへの移行を想定しています:
- 🌐 Blazor Web Apps - サーバーサイドとクライアントサイドのハイブリッドレンダリング
- 🖥️ Blazor WebAssembly - クライアントサイドでの.NET実行
- 🏗️ ASP.NET Core MVC - 従来のMVCパターンの継承
- 🔌 ASP.NET Core Web API - RESTful APIの構築
なぜモダナイズしなければならないのか?
「動いているものは触るな」という格言がありますが、レガシーシステムを放置することには多くのリスクが伴います。🤔
1. コストの明瞭化 💰
特にクラウドへの移行を検討する場合、従量課金制によりコストが可視化されます。オンプレミス環境では見えにくかったインフラコストが明確になり、最適化の機会が生まれます。
2. 最新機能へのアクセス 🤖
AIをはじめとする最新技術は、モダンなフレームワークでの利用が前提となっています。.NET Frameworkでは利用できない機能やライブラリが増えており、ビジネス競争力の低下につながります。
3. セキュリティの問題 🔒
古いフレームワークは脆弱性が発見されても修正されないケースがあります。セキュリティパッチの提供が終了したシステムを運用し続けることは、組織にとって大きなリスクです。
4. パフォーマンスの問題 ⚡
.NET Coreおよび.NETは、.NET Frameworkと比較して大幅なパフォーマンス改善が施されています。同じハードウェアでより高いスループットを実現できます。
.NET Frameworkベースのアプリケーションの分類
移行の難易度はアプリケーションの種類によって大きく異なります。📊
移行が比較的容易なグループ ✅
.NETにも同様のフレームワークが存在するため、比較的スムーズに移行できます:
| フレームワーク | 移行先 |
|---|---|
| Windows Forms | Windows Forms (.NET) |
| コンソールアプリ | コンソールアプリ (.NET) |
| ASP.NET MVC | ASP.NET Core MVC |
| WCF(クライアント) | CoreWCF / gRPC |
移行が困難なグループ ⚠️
.NETに同様のフレームワークが存在しないため、アーキテクチャの見直しが必要です:
| フレームワーク | 課題 |
|---|---|
| ASP.NET Web Forms | 同等のフレームワークが存在しない。Blazorへの書き換えが必要 |
| WCF(サーバー) | CoreWCFへの移行またはgRPCへの再設計が必要 |
.NETのサポート期間について
モダナイゼーションを計画する上で、サポート期間の理解は重要です。📅
- 🏢 .NET Framework - OSのサポート期間に準じる(Windows Serverと同期)
- 🟢 .NET LTS(.NET 8など)- リリースより36ヶ月のサポート
- 🟡 .NET STS(.NET 9など)- リリースより24ヶ月のサポート
また、Azureリソースでのランタイムサポートも考慮が必要です。.NETはApp Serviceなどリリースと同時にサポートされるため、クラウドネイティブな開発がスムーズに行えます。☁️
とはいえ、開発者にとってAzureって難しい
ここまで読んで「よし、Azureに移行しよう!」と思った方、ちょっと待ってください。正直なところ、開発者にとってAzureは難しいです。😅
サービスの数は200以上、ネットワーク・セキュリティ・ID管理など、アプリケーション開発とは異なるスキルセットが求められます。しかし、だからこそ勉強しましょう!
📖 おすすめリソース
Azureの全体像を把握するには、体系的な学習が効果的です:
- 📘 Azureの知識地図(ISBN: 978-4-297-14903-1)- クラウドの基礎から実装・運用管理まで網羅
- 🎓 Microsoft Learn - 無料のオンライン学習プラットフォーム
- 📜 Azure認定資格 - AZ-900から始めて体系的に学ぶ
Azure Cloud Adoption Framework(CAF)を読もう
モダナイゼーションを成功させるには、技術だけでなく組織の準備が必要です。MicrosoftはAzure導入のベストプラクティスとしてCloud Adoption Framework(CAF) を提供しています。🏗️
CAFの構成要素
CAFは以下のフェーズで構成されています:
| フェーズ | 内容 |
|---|---|
| 🎯 クラウド導入の動機 | なぜクラウドに移行するのか、ビジネス目標の明確化 |
| 📋 導入戦略 | 移行のアプローチ、優先順位の決定 |
| 🛬 導入準備(ランディングゾーン) | セキュアで拡張可能な基盤環境の構築 |
| 🚀 導入 | マイグレーション・モダナイゼーション・イノベーション |
| 🔧 管理 | 運用・監視・最適化 |
| 🔒 セキュリティ | ゼロトラスト、コンプライアンス対応 |
モダナイズの導入戦略
CAFでは、モダナイゼーションにおいて以下の2つの観点を重視しています:
1. プロセスのモダン化 🔄
- DevOps手法を採用しよう - 開発と運用の壁を取り払い、継続的な改善サイクルを確立
- CI/CDを採用して高速なデリバリーを実現しよう - GitHub ActionsやAzure Pipelinesによる自動化
2. アプリケーションとデータベースのモダン化 💾
- PaaSソリューションを採用しよう - インフラ管理の負担を軽減し、アプリケーション開発に集中
アーキテクチャセンターを読もう
「具体的にどう設計すればいいの?」という疑問には、Azureアーキテクチャセンターが答えてくれます。📐
実例ベースの設計パターン
アーキテクチャセンターでは、どのように設計したらよいか実例を元に明示されています。例えば:
- 🌐 .NETにおける信頼性の高いWebアプリパターン - マルチリージョン構成、プライベートエンドポイント、キャッシュ戦略
- 🔌 マイクロサービスアーキテクチャ - サービス間通信、イベント駆動設計
- 📊 データ分析パイプライン - リアルタイム処理とバッチ処理の組み合わせ
典型的な.NET Webアプリケーションのアーキテクチャには以下の要素が含まれます:
- 🌍 DNS + Web Application Firewall + Load Balancer
- 🔐 Identity and Access Management(Entra ID)
- 🖥️ Application Platform(Web App Code)
- 📈 Application Performance Monitoring(Application Insights)
- 🔒 Virtual Network + Private Endpoints
- 💾 Cache + Database + Other Azure Services
アプリケーションのモダン化:サービス選定の考え方
いよいよ本題です。ASP.NET Coreアプリケーションをホストするサービスをどう選ぶか?🤔
ソリューションのコントロールと生産性のバランス
サービス選定において最も重要な観点は、コントロール(柔軟性)と生産性(開発速度)のトレードオフです。
| コントロールと生産性 | ソリューション | 説明 |
|---|---|---|
| 🔧 最大のコントロール | AKS、Azure Red Hat OpenShift | インフラのコントロールが可能。運用はやや大変 |
| ⚖️ バランス | Azure App Service、Azure Spring Apps、Azure Functions | コードの開発に重点。インフラの自動化 |
| 🚀 最大の生産性 | Power Apps、Power Automate | リードタイムを最短化。ローコード/ノーコード |
ASP.NET Core開発者への推奨
ASP.NET Coreアプリケーションの場合、多くのケースでバランス型のサービスが適切です:
- 🌐 Azure App Service - 最も一般的な選択肢。WebアプリやAPIに最適
- ⚡ Azure Functions - イベント駆動型の処理、マイクロサービスに最適
- 🐳 Azure Container Apps - コンテナベースでありながらKubernetesの複雑さを隠蔽
ただし、以下の場合は最大のコントロールが必要になることも:
- 🔧 特殊なランタイム要件がある
- 🌐 複雑なネットワーク構成が必要
- 📦 既存のKubernetesマニフェストを活用したい
IaaSかPaaSか
モダナイゼーションにおけるインフラ選定で最初に直面する問題が「IaaSかPaaSか」です。🤔
PaaSを選択すべき理由
モダナイゼーションという文脈からは、PaaS中心の選択となるのは自明です。
- ✅ 運用にかかるあらゆる面倒から解放 - OSのパッチ適用、ミドルウェアの更新などをAzureに任せられる
- ✅ CAFでも明確に推奨 - モダナイゼーションという文脈ではPaaSの選択を明確に謳っている
- ✅ スケーラビリティ - 需要に応じた自動スケーリングが容易
- ✅ 開発に集中 - インフラ管理ではなく、ビジネスロジックの実装に時間を使える
IaaS(VM)を選択するケース
基本的にどうしてもPaaSでできないものがIaaS(VM)を使用することになるという考え方が重要です:
| ケース | 理由 |
|---|---|
| 🖥️ レガシーアプリの一時的な移行先 | リフト&シフトでまず動かす |
| 🔧 特殊なソフトウェア要件 | PaaSでサポートされていないミドルウェア |
| 📜 ライセンス制約 | 特定のVM上でのみ動作が許可されている |
| 🔒 規制要件 | 専用のコンピューティング環境が必要 |
ステートレスにできるか
PaaSを選択する上で避けて通れないのが「ステートレス設計」です。🔄
なぜステートレスが重要なのか
本質的に、アプリケーションをステートレスに再設計すべきです。その最大の理由は:
⚠️ アプリケーションに状態を持っているとスケールアウトできない
スケールアウト(水平スケーリング)では、複数のインスタンスが同時にリクエストを処理します。もしインスタンスAに保存された状態がインスタンスBからアクセスできなければ、ユーザーは一貫した体験を得られません。😵
ステートフル vs ステートレス
| 設計 | 動作 | スケーラビリティ |
|---|---|---|
| 😢 ステートフル(従来型) | セッションをインスタンスに保存 → 同じインスタンスに固定 | スケールアウト困難 |
| 😊 ステートレス(推奨) | どのインスタンスでも処理可能 → 外部ストレージ(Redis等)で状態を共有 | スケールアウト容易 |
セッションどうするの?
ASP.NET Core MVCアプリケーションで特に問題になるのが「セッション管理」です。🍪
問題点
従来のASP.NETアプリケーションでは、セッション情報をアプリケーションサーバーのメモリ(InProc)に持たせることが一般的でした。しかし:
- ❌ アプリケーションサーバーに持たせるとスケールアウト不能
- ❌ インスタンスが再起動するとセッションが消失
- ❌ 複数インスタンス間でセッションを共有できない
解決策:Azure Managed Redis
Azure Managed Redis(旧 Azure Cache for Redis)などに情報を持たせるようにすることで、これらの問題を解決できます。🚀
⚠️ 注意: Azure Cache for Redisは廃止が予定されており、後継サービスとしてAzure Managed Redisへの移行が推奨されています。
// Program.cs での設定例
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("Redis");
options.InstanceName = "MyApp_";
});
// 分散セッションの有効化
builder.Services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(30);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
Azure Managed Redisのメリット
| メリット | 説明 |
|---|---|
| 🔄 高可用性 | アクティブ geo レプリケーションとフェイルオーバーをサポート |
| ⚡ 高速 | インメモリデータストアで低レイテンシ |
| 📈 スケーラブル | クラスタリングによる水平スケーリング |
| 🔒 セキュア | VNet統合、プライベートエンドポイント対応 |
| 🆕 最新機能 | Redis 7.4対応、RediSearch、RedisBloomなどのモジュール対応 |
セッション以外の状態管理
セッション以外にも、以下のような状態を外部化する必要があります:
- 📁 ファイルアップロード → Azure Blob Storage
- 🔐 認証トークン → Azure Managed Redis / データベース
- 📊 一時的な計算結果 → Azure Managed Redis
- 📝 ユーザー設定 → データベース(Azure SQL、Cosmos DBなど)
コンピューティングリソースの選択
ここからは、ASP.NET Coreアプリケーションをホストする具体的なAzureサービスを見ていきましょう。🖥️
第一選択肢は App Service
結論から言うと、第一選択肢はAzure App Serviceです。
既存のアプリに対して最も最小の変更で最もよい効果が得られる可能性が高いからです。まずはApp Serviceで要件を満たせるかを検討し、満たせない場合に他のサービスを検討するというアプローチが効率的です。
Azure App Service
まず、App Serviceが使えないか検討
App Serviceはコードベース・コンテナーともに第一選択肢として考えるべきサービスです。🌟
| 特徴 | 説明 |
|---|---|
| 🔧 運用まで考慮すると一番楽 | OSパッチ、ランタイム更新はAzureにお任せ |
| 📈 インスタンス数複数 | 自動スケーリングで負荷に対応 |
| 💎 Premiumプランを選択する | VNet統合、プライベートエンドポイント対応 |
App Serviceの主な機能
- ✅ デプロイスロット - ステージング環境でのテスト後にスワップ
- ✅ 自動スケーリング - CPU/メモリ使用率に基づくスケールアウト
- ✅ カスタムドメイン&SSL - 独自ドメインとHTTPS対応
- ✅ 認証/認可 - Easy Auth(組み込み認証)
- ✅ Application Insights統合 - パフォーマンス監視
本番環境ではPremiumプランを
開発・テスト環境ではBasicやStandardでも問題ありませんが、本番環境ではPremiumプラン(P1v3以上) を推奨します:
- 🔒 VNet統合 - プライベートネットワーク内でのセキュアな通信
- 🚀 より高いパフォーマンス - より多くのCPU、メモリ
- 📊 ゾーン冗長 - 高可用性の実現
App Service Managed Instance(プレビュー)🆕
App Service Managed Instanceは、レガシーシステムの段階的なPaaS移行を支援する新しいホスティングオプションです。
こんな場合にManaged Instanceを検討
| ユースケース | 説明 |
|---|---|
| 🏛️ レガシーWindows互換性 | COMコンポーネント、レジストリ変更、MSIインストーラーが必要 |
| 🔧 IIS Managerアクセス | IIS設定のカスタマイズ、診断用RDPアクセス |
| 📁 ネットワーク共有 | UNCパスやドライブマッピングが必要 |
| 🔄 最小限のリファクタリングで移行 | 完全な書き換えなしの「Lift and Improve」移行 |
通常のApp Serviceとの比較
| 機能 | 通常のApp Service | Managed Instance |
|---|---|---|
| OS | Windows / Linux | Windows のみ |
| COMコンポーネント | ❌ | ✅ |
| レジストリアクセス | ❌ | ✅ |
| MSIインストーラー | ❌ | ✅ |
| RDPアクセス | ❌ | ✅(診断用) |
| PowerShellインストールスクリプト | ❌ | ✅ |
| カスタムフォント | ❌ | ✅ |
| GAC(グローバルアセンブリキャッシュ) | ❌ | ✅ |
主な機能
- 📜 構成(インストール)スクリプト - PowerShellスクリプトで起動時にOS/ミドルウェアを構成
- 🔐 レジストリアダプター - Azure Key Vault連携でレジストリキーを安全に管理
- 📂 ストレージマウント - Azure Files、UNCパス、ドライブマッピング対応
- 🖥️ RDPアクセス - Azure Bastion経由でJust-in-Time診断アクセス
- 🔒 プランレベルのVNet統合 - プライベートネットワーク分離
段階的移行のシナリオ
Managed Instanceは「完全なクラウドネイティブ化」と「IaaSでのLift & Shift」の間を埋める選択肢です。
| 移行戦略 | 対象 | サービス |
|---|---|---|
| 🚀 Replatform(クラウドネイティブ) | モダンな.NET Coreアプリ | 通常のApp Service |
| 🔄 Lift and Improve | レガシー依存のある.NET Frameworkアプリ | Managed Instance |
| 📦 Lift and Shift | 変更不可のレガシーアプリ | Azure VM(IaaS) |
// 例:Managed Instanceで利用可能なレガシーコード
// COMコンポーネントの利用
var excelApp = new Microsoft.Office.Interop.Excel.Application();
// レジストリアクセス
var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\MyApp");
// カスタムフォントを使用した描画
using var font = new Font("MyCustomFont", 12);
利用の注意点
- ⚠️ RDPでの変更は永続化されません - 再起動やメンテナンスで失われます
- ✅ 永続的な構成は必ずインストールスクリプトで行う
- 🔐 シークレットはKey Vaultで一元管理
Azure Static Web Apps
実質的にAzure Functionsと組み合わせて使う前提
Azure Static Web Appsは、静的コンテンツのホスティングに特化したサービスです。📄
| 用途 | 説明 |
|---|---|
| 🖥️ Blazor WebAssemblyの場合に考慮 | クライアントサイドで完結するアプリに最適 |
| 🔌 バックエンドをWeb APIとしたい場合 | App Serviceとの組み合わせを検討 |
構成パターン
| パターン | フロントエンド | バックエンド | 用途 |
|---|---|---|---|
| パターン1 | Static Web Apps | 組み込みAzure Functions | シンプルなAPI連携 |
| パターン2 | Static Web Apps | Azure App Service (Web API) | 複雑な処理や既存APIの活用 |
💡 バックエンドで複雑な処理が必要な場合や、既存のASP.NET Core Web APIを活用したい場合は、App Serviceとの組み合わせを検討しましょう。
Azure Functions
HTTPトリガーでバックエンドとして構築
Azure Functionsは、イベント駆動型のサーバーレスコンピューティングサービスです。⚡
| 特徴 | 説明 |
|---|---|
| 💰 小規模なWebシステムにおいて最もコスト安となる可能性 | 従量課金プランで使った分だけ支払い |
| 🔌 HTTPトリガー | REST APIとして利用可能 |
| 🎯 マイクロサービス | 機能単位での分割に最適 |
Functionsが適しているケース
- ✅ リクエスト頻度が低〜中程度のAPI
- ✅ バッチ処理やスケジュール実行
- ✅ イベント駆動型の処理(キュー、Blob変更など)
- ✅ Webhookエンドポイント
Functionsが適さないケース
- ❌ 常時接続が必要(WebSocket等)→ App Serviceを検討
- ❌ 長時間実行が必要な処理(10分以上)→ Durable Functionsまたは他サービス
- ❌ 複雑なルーティングが必要 → App Serviceを検討
Azure Spring Apps
⚠️ 廃止がアナウンスされているため新規採用は避ける
Azure Spring Appsは廃止がアナウンスされているため、これからの新規採用はありえません。🚫
既存でAzure Spring Appsを利用している場合は、以下への移行を検討してください:
| 移行先 | 説明 |
|---|---|
| 🐳 Azure Container Apps | コンテナベースのPaaSとして最も近い選択肢 |
| 🌿 VMware Tanzu | Spring専用の環境が必要な場合 |
📝 ASP.NET Core開発者にとってはそもそも関係のないサービスですが、Javaチームがある組織では移行計画の検討が必要です。
Azure Container Apps
App Serviceの次に検討するサービス
Azure Container Appsは、Kubernetesの複雑さを隠蔽しつつコンテナの柔軟性を提供するサービスです。🐳
| 特徴 | 説明 |
|---|---|
| 🎯 コンテナネイティブ | Dockerイメージをそのままデプロイ |
| 📈 自動スケーリング | KEDA(Kubernetes Event-driven Autoscaling)ベース |
| 🔄 マイクロサービス対応 | Daprによるサービス間通信 |
Container Appsを選ぶケース
- ✅ コンテナ化されたアプリケーション
- ✅ マイクロサービスアーキテクチャ
- ✅ イベント駆動型のスケーリングが必要
- ✅ Kubernetesの運用負荷を避けたい
Azure Kubernetes Service (AKS)
大規模なマイクロサービスにおいて検討する
AKSは最大のコントロールを提供しますが、それに伴う運用負荷も大きいサービスです。☸️
| 考慮点 | 説明 |
|---|---|
| 👨💻 運用には高度な知識を持ったインフラ担当者が必要 | Kubernetesの学習コストは高い |
| 💰 小規模なシステムでは運用コストの面から見合わない | 人的コストも含めたTCOを考慮 |
| 🎯 大規模マイクロサービスにおいて検討 | 数十〜数百のサービスを運用する場合 |
AKS Automatic:運用負荷を軽減する新しい選択肢 🆕
AKS Automaticは、従来のAKS(AKS Standard)の運用負荷を大幅に軽減する新しいオプションです。
AKS Automaticは、Kubernetesの最も一般的なタスクを高速かつスムーズに行えるようにしつつ、Kubernetesの柔軟性と拡張性を維持します。
AKS Automaticの特徴
| 特徴 | 説明 |
|---|---|
| 🚀 Production ready by default | 本番環境に最適化された事前設定。ノードプールは自動で管理・スケーリング |
| 🔒 Built-in best practices and safeguards | セキュリティ設定がデフォルトで有効。ノードとクラスターコンポーネントの自動パッチ |
| ⚡ Code to Kubernetes in minutes | コンテナイメージから数分でベストプラクティスに沿ったアプリをデプロイ |
AKS Standard vs AKS Automatic
| 観点 | AKS Standard | AKS Automatic |
|---|---|---|
| ノード管理 | 手動でノードプールを作成・管理 | Node Autoprovisioning で自動管理 |
| スケーリング | 手動 or Cluster Autoscaler | 自動(HPA、KEDA、VPA が有効) |
| セキュリティ | オプションで設定 | Deployment Safeguards がデフォルト有効 |
| ネットワーク | 複数の選択肢から選択 | Azure CNI Overlay with Cilium(事前構成) |
| SLA | Free/Standard/Premium から選択 | Standard tier + Pod readiness SLA(99.9%) |
AKS Automaticを選ぶケース
- ✅ Kubernetesを使いたいが運用負荷を最小化したい
- ✅ ベストプラクティスに沿った設定を自動で適用したい
- ✅ Container Appsでは柔軟性が足りないが、AKS Standardは複雑すぎる
💡 ポイント: AKS AutomaticはContainer AppsとAKS Standardの中間に位置するサービスです。Kubernetesの柔軟性を保ちつつ、運用負荷を軽減したい場合に検討してください。
AKSを選ぶべきケース
- ✅ 大規模なマイクロサービスアーキテクチャ
- ✅ 既存のKubernetesマニフェストを活用したい
- ✅ 高度なネットワーク制御が必要
- ✅ マルチクラウド/ハイブリッドクラウド戦略
AKSを避けるべきケース
- ❌ チームにKubernetes経験者がいない
- ❌ アプリケーション数が少ない(1〜5個程度)
- ❌ 運用負荷を最小化したい
バッチどうするか問題
Webアプリケーションのモダナイゼーションでは、バッチ処理も重要な検討事項です。🔄
従来の.NET Frameworkアプリケーションでは、Windowsタスクスケジューラやコンソールアプリケーションでバッチ処理を実行していたケースが多いですが、クラウド環境ではどうすべきでしょうか?
選択肢の広がり:WebJobs on Linux
LinuxのWebJobsがGAになって選択肢が広がりました。これにより、App Service上でバックグラウンドタスクを実行できるようになっています。
| オプション | 説明 |
|---|---|
| 🖥️ WebJobs(Windows) | 従来からの選択肢。App Service上で実行 |
| 🐧 WebJobs(Linux) | Linux App Serviceでも利用可能に |
| ⚡ Azure Functions | 柔軟性が高い。第一選択肢として推奨 |
第一選択肢はAzure Functions
とはいえ、柔軟性を考えればAzure Functionsのほうが第一選択肢です。
Azure Functionsには以下のメリットがあります:
- ✅ 多様なトリガー - タイマー、キュー、Blob、HTTPなど
- ✅ 従量課金 - 実行時間に応じた課金で小規模バッチに最適
- ✅ スケーラビリティ - 並列実行が容易
- ✅ 監視・ログ - Application Insightsとの統合
Azure Functionsをバッチとして使用する際の考慮事項
Azure Functionsをバッチ処理に使用する際の最大の考慮事項は実行時間です。⏱️
| プラン | 最大実行時間 | 用途 |
|---|---|---|
| 🆓 従量課金プラン | 10分(デフォルト5分) | 短時間のバッチ処理 |
| 💎 Premiumプラン | 無制限(デフォルト30分) | 長時間のバッチ処理 |
| 🔧 Dedicated(App Service)プラン | 無制限 | 常時実行が必要な場合 |
| ⚡ Flex従量課金プラン | 無制限(デフォルト30分) | スケーラビリティと長時間実行の両立 |
⚠️ 注意: 長時間かかるタスクは通常の従量課金のFunctionは使えません。PremiumプランまたはFlex従量課金プランを検討してください。
Durable Functionsによる長時間処理
長時間の処理や複雑なワークフローにはDurable Functionsが有効です:
// オーケストレーター関数の例
[FunctionName("BatchOrchestrator")]
public static async Task RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
var items = await context.CallActivityAsync<List<Item>>("GetItems", null);
// 並列処理
var tasks = items.Select(item =>
context.CallActivityAsync("ProcessItem", item));
await Task.WhenAll(tasks);
await context.CallActivityAsync("SendNotification", "完了しました");
}
Durable Task Scheduler(DTS):高性能なバックエンドプロバイダー 🆕
業務系のバッチ処理はだいたいデータ処理なので、Durable Task Scheduler(DTS) に向いています。
DTSは現在プレビューとして利用可能で、Durable Functionsの新しいバックエンドプロバイダーです。従来のAzure Storageプロバイダーと比較して約5倍のスループットを実現します。
DTSの主な特徴
| 特徴 | 説明 |
|---|---|
| 🚀 高パフォーマンス | Azure Storageプロバイダーの約5倍のスループット |
| 📊 組み込みダッシュボード | オーケストレーションの監視・管理が容易 |
| 🔧 フルマネージド | ストレージアカウントの管理が不要 |
| 🔐 マネージドID対応 | セキュアな認証 |
DTSの利用方法
既存のDurable Functionsアプリはコード変更なしでDTSを利用できます。host.jsonの設定変更のみで移行可能です:
{
"extensions": {
"durableTask": {
"hubName": "%TASKHUB_NAME%",
"storageProvider": {
"type": "azureManaged",
"connectionStringName": "DURABLE_TASK_SCHEDULER_CONNECTION_STRING"
}
}
}
}
DTSの価格モデル
| プラン | 説明 |
|---|---|
| 💎 Dedicated | 予約済みリソースで安定したパフォーマンス |
| ⚡ Consumption(プレビュー) | アクション単位の従量課金 |
💡 DTSは現在プレビュー段階ですが、業務系バッチの救世主として期待大です!GAが待ち遠しいですね 🎉
バッチ処理の選定フロー
| 条件 | 推奨サービス |
|---|---|
| 実行時間10分以内 | Azure Functions(従量課金)✅ |
| 実行時間10分超・シンプルな処理 | Azure Functions(Premium/Flex)✅ |
| 複雑なワークフロー | Durable Functions ✅ |
| App Serviceと同じインフラで実行したい | WebJobs |
| 大量データの分散処理 | Durable Functions + DTS |
サービス選定フローチャート
最後に、サービス選定の思考プロセスをまとめます。🗺️
| 条件 | 推奨サービス |
|---|---|
| コンテナ化が不要 | Azure App Service ✅ |
| コンテナ化必須 + Kubernetes経験なし | Azure Container Apps ✅ |
| コンテナ化必須 + Kubernetes経験あり + 小〜中規模 | Azure Container Apps ✅ |
| コンテナ化必須 + Kubernetes経験あり + 大規模マイクロサービス | AKS ✅ |
| 静的サイト + API | Static Web Apps + Functions/App Service |
| イベント駆動・小規模API | Azure Functions |
データベースの選択 🗄️
インフラのモダナイゼーションにおいて、データベースの選択は重要な決定事項です。Azureでは用途に応じて複数の選択肢があります。
データベースの種類
データベースは大きく分けて2種類あります:
| 種類 | 特徴 | Azure サービス例 |
|---|---|---|
| 🗃️ RDB(リレーショナル) | 構造化データ、ACID準拠、SQL | Azure SQL Database, MySQL, PostgreSQL |
| 📦 NoSQL | スキーマレス、スケーラブル | Cosmos DB, Table Storage |
オンプレミスからの移行マッピング
| オンプレミス | Azure サービス |
|---|---|
| SQL Server | Azure SQL Database / SQL Managed Instance |
| Oracle | Azure Database for PostgreSQL(移行)/ Oracle on Azure VM |
| MySQL | Azure Database for MySQL |
| PostgreSQL | Azure Database for PostgreSQL |
Azure SQL Database を第一選択に 🥇
SQL Serverからの移行の場合、Azure SQL Databaseをまず検討しましょう。
- ✅ フルマネージドなPaaSサービス
- ✅ 自動バックアップ、パッチ適用
- ✅ 高可用性が組み込み
- ✅ スケーリングが容易
- ✅ Azure Managed Redisと組み合わせてキャッシュ戦略を構築
Azure SQL Database の主な機能:
- 🔄 自動チューニング - クエリパフォーマンスの自動最適化
- 🛡️ Advanced Threat Protection - セキュリティ脅威の検出
- 📊 Query Performance Insight - クエリの分析と最適化支援
- 🌍 geo レプリケーション - グローバルな可用性
Azure SQL Managed Instance という選択肢 🏢
SQL Databaseではカバーできない要件がある場合はAzure SQL Managed Instanceを検討します。
こんな場合にManaged Instanceを選択:
- 📅 タイムゾーン - JSTなど特定のタイムゾーンで運用したい
- 🔗 SQL Server Agent - ジョブのスケジューリングが必要
- 📧 Database Mail - メール送信機能が必要
- 🔐 クロスデータベースクエリ - 複数データベース間のクエリ
- 🏛️ CLR統合 - .NETアセンブリの実行
| 機能 | SQL Database | SQL Managed Instance |
|---|---|---|
| タイムゾーン設定 | UTC固定 | カスタマイズ可能 ✅ |
| SQL Server Agent | ❌ | ✅ |
| リンクサーバー | ❌ | ✅ |
| CLR統合 | 限定的 | ✅ |
| VNet統合 | サービスエンドポイント | ネイティブ ✅ |
Table Storage - シンプルなKey-Valueストア 🔑
Azure Table StorageはKey-Value方式のシンプルなデータストアです。
特徴:
- 💰 非常に安価
- 📈 件数が少ない場合に最適
- 🔧 スキーマレス
- ⚡ 高速なKey-Value検索
ただし、適用できるユースケースは限定的です。設定情報の保存やシンプルなログデータなど、複雑なクエリが不要な場合に検討しましょう。
Cosmos DB - グローバルスケールのNoSQL 🌏
グローバル分散が必要な場合や、スキーマレスなドキュメントを扱う場合はAzure Cosmos DBが選択肢になります。
- 🌍 マルチリージョン書き込み
- ⚡ シングルミリ秒の低レイテンシ
- 📊 複数のAPIモデル(SQL、MongoDB、Cassandra等)
データベース選択フローチャート
| 条件 | 推奨サービス |
|---|---|
| SQL Serverからの移行 + 特殊機能不要 | Azure SQL Database ✅ |
| SQL Serverからの移行 + 特殊機能(Agent, タイムゾーン等)必要 | Azure SQL Managed Instance ✅ |
| MySQLからの移行 | Azure Database for MySQL |
| PostgreSQLからの移行 | Azure Database for PostgreSQL |
| NoSQL + グローバル分散必要 | Cosmos DB ✅ |
| NoSQL + シンプルなKey-Value | Table Storage(安価) |
| NoSQL + それ以外 | Cosmos DB ✅ |
DevOpsツールを導入する 🔧
モダナイゼーションはインフラだけでなく、開発プロセスの近代化も重要です。DevOpsツールを導入して、継続的な改善サイクルを確立しましょう。
DevOpsツールカテゴリ一覧
| カテゴリ | 説明 | ツール例 |
|---|---|---|
| 📁 ソース管理 | コードリポジトリ | GitHub、Azure Repos |
| 🔄 CI/CDパイプライン | 継続的にビルドやテストデプロイ | GitHub Actions、Azure Pipelines |
| 📋 タスクボード | 作業を計画、追跡、議論 | GitHub Projects、Azure Boards、Redmine |
| 📦 パッケージマネージャー | パッケージを発行する | Azure Artifacts、GitHub Packages |
| 🧪 テスト管理 | テストと品質保証を実行する | Azure Test Plans |
CI/CD どうするか問題 🤔
CI/CDツールの選択は悩ましい問題ですが、結論から言うとGitHub Actionsをお勧めします。
GitHub を選ぶ理由:
-
🤖 GitHub Copilot の存在
- 開発効率が劇的に向上
- リポジトリベースをGitHubに寄せたい理由として十分
- Copilot使わない選択肢はもうないでしょ!
-
🌐 Azure VNETでGitHubホストランナーが使用可能に
- セルフホステッドランナーを構築する理由がほぼなくなった
- ネットワークセキュリティを維持しながらマネージドランナーを利用可能
-
⚖️ CI/CD観点での機能差は小さい
- GitHub ActionsとAzure Pipelinesでできることに大きな差はない
- エコシステムとマーケットプレイスが充実
GitHub Actions vs Azure Pipelines
| 観点 | GitHub Actions | Azure Pipelines |
|---|---|---|
| ソースコードとの統合 | ⭐⭐⭐ ネイティブ | ⭐⭐ 連携必要 |
| GitHub Copilot | ⭐⭐⭐ フル統合 | ⭐ 限定的 |
| VNet統合ランナー | ✅ 対応 | ✅ 対応 |
| マーケットプレイス | 豊富 | 豊富 |
| Azure統合 | ✅ 良好 | ⭐⭐⭐ ネイティブ |
Azure VNet統合GitHubホストランナー 🔒
従来、セキュリティ要件の厳しい環境ではセルフホステッドランナーが必須でしたが、Azure VNet統合により状況が変わりました。
| 観点 | 従来の課題 | VNet統合後 |
|---|---|---|
| ランナー管理 | ❌ セルフホステッドランナーの構築・運用が必要 | ✅ GitHubマネージドランナーをVNet内で実行 |
| スケーリング | ❌ スケーリングの管理が煩雑 | ✅ 自動スケーリング対応 |
| セキュリティ | ❌ セキュリティパッチの適用が必要 | ✅ プライベートエンドポイント経由でアクセス |
| 運用負荷 | ❌ 高い | ✅ 大幅削減 |
推奨DevOps構成 🏆
GitHub(メイン)
| ツール | 用途 |
|---|---|
| 📁 GitHub Repos | ソース管理 |
| 🔄 GitHub Actions | CI/CD(VNet統合対応) |
| 📋 GitHub Projects | タスク管理 |
| 🤖 GitHub Copilot | AI開発支援(絶対使う!) |
Azure(補完)
| ツール | 用途 |
|---|---|
| 📦 Azure Artifacts | パッケージ管理 |
| 🧪 Azure Test Plans | テスト管理(必要時) |
まとめ
ASP.NETアプリケーションのモダナイゼーションにおけるインフラ選定のポイントをまとめます。📝
🎯 選定の基本方針
- PaaSを第一選択として検討する
- App Serviceをまず検討し、要件に合わない場合に他を検討
- ステートレス設計を前提にアーキテクチャを考える
- セッションや状態はAzure Managed Redisなどに外部化
- データベースはAzure SQL Databaseを第一選択
- DevOpsはGitHub + GitHub Actionsでシンプルに
📊 サービス比較まとめ
| カテゴリ | 第一選択 | 代替選択肢 |
|---|---|---|
| 🖥️ コンピューティング | App Service | Container Apps, AKS |
| 🗄️ データベース | Azure SQL Database | SQL Managed Instance |
| ⚡ キャッシュ | Azure Managed Redis | - |
| 📁 ソース管理 | GitHub | Azure Repos |
| 🔄 CI/CD | GitHub Actions | Azure Pipelines |
🚀 次のステップ
モダナイゼーションは一朝一夕で完了するものではありません。以下のステップで進めていくことをお勧めします:
- 📖 学習 - Azure CAF、アーキテクチャセンターを読む
- 🔍 現状分析 - 既存アプリの依存関係、状態管理の洗い出し
- 🛠️ DevOps整備 - GitHub + GitHub Actionsでパイプライン構築
- 🧪 PoC - 小規模なアプリでApp Serviceへのデプロイを試す
- 📋 計画 - 段階的な移行計画の策定
- 🚀 実行 - CI/CDパイプラインを活用しながら移行
🗺️ 全体構成イメージ
開発環境
| コンポーネント | 説明 |
|---|---|
| 💻 VS Code + Copilot | 開発IDE |
| 🔄 GitHub Actions | CI/CDパイプライン |
| 🤖 GitHub Copilot | AI開発支援(必須!) |
⬇️ CI/CDでデプロイ
Azure環境
| コンポーネント | 説明 |
|---|---|
| 🌐 App Service | Webアプリケーション |
| 🗄️ Azure SQL Database | データベース |
| ⚡ Azure Managed Redis | キャッシュ |
| ⚙️ Azure Functions | バッチ/イベント処理 |
クラウドアプリケーションの考慮事項 ⚠️
Azure(クラウド)環境では、オンプレミスとは異なる動作環境に注意が必要です。特に日本のシステムでは見落としがちなポイントがあります。
UTCで動作するリソース 🌐
多くのAzureリソースはUTC(協定世界時) で動作しています。
| 観点 | オンプレミス | Azure |
|---|---|---|
| 🕐 システム時刻 | JST(日本標準時) | UTC |
| 📅 ログのタイムスタンプ | JST | UTC |
| ⏰ スケジュール実行 | JST基準 | UTC基準が多い |
逃げ道のあるサービス:
- 🏃 App Service - タイムゾーン設定(
WEBSITE_TIME_ZONE)で変更可能 - 🏃 SQL Managed Instance - JSTなど任意のタイムゾーンを設定可能
- ❌ Azure SQL Database - UTC固定(アプリケーション側で対応が必要)
ノンカルチャー(Invariant Culture)で動作 🌍
Azureの多くのサービスはインバリアントカルチャー(特定の文化圏に依存しない設定)で動作します。
| 観点 | ローカル開発環境 | Azure |
|---|---|---|
| 🗾 カルチャー | ja-JP(日本語) | Invariant Culture |
| 📝 文字列比較 | 日本語ロケール | ロケール非依存 |
| 🔢 数値・日付フォーマット | 日本形式 | 標準形式 |
タイムゾーンについての設計 🕐
クラウド環境でのタイムゾーン設計は、モダナイゼーションで最も見落とされがちな点の一つです。
設計方針
| レイヤー | 推奨 | 理由 |
|---|---|---|
| 💾 データベース | UTC | 標準化、タイムゾーン変更に強い |
| 🔧 ビジネスロジック | UTC | 計算・比較が明確 |
| 👁️ 表示(View) | JST変換 | ユーザーに分かりやすい |
DateTimeOffsetを使用する 📅
日時を表現する型は DateTimeOffset を使用しましょう。
// ❌ 非推奨:DateTime(タイムゾーン情報がない)
DateTime now = DateTime.Now; // ローカル時刻だが、どのタイムゾーンか不明
// ✅ 推奨:DateTimeOffset(タイムゾーン情報を含む)
DateTimeOffset nowUtc = DateTimeOffset.UtcNow; // UTC時刻
DateTimeOffset nowJst = TimeZoneInfo.ConvertTime(
DateTimeOffset.UtcNow,
TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time")
);
DateTimeOffsetを使う理由:
- ⏰ 時差を考慮した表現が必要になるので、必然的にタイムゾーンを意識できる
- 🔧 TimeProviderから返される型も
DateTimeOffsetなので事実上標準 - 🌍 グローバル対応が将来的に必要になった場合も対応しやすい
表示時の変換パターン
// サービス層:UTCで処理
public class OrderService
{
public DateTimeOffset GetOrderTime() => DateTimeOffset.UtcNow;
}
// 表示層(View/ViewModel):JSTに変換
public class OrderViewModel
{
private static readonly TimeZoneInfo JstTimeZone =
TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
public string OrderTimeDisplay =>
TimeZoneInfo.ConvertTime(Order.OrderTime, JstTimeZone)
.ToString("yyyy/MM/dd HH:mm:ss");
}
💡 ポイント: 表示する時にViewまたはViewに近いところでJSTに変換する
カルチャーについて 🗾
stringクラスは特に要注意 ⚠️
stringクラスのメソッドはカルチャーによって動作が変わるものがあります。
// ❌ カルチャー依存(環境によって結果が変わる可能性)
string upper = text.ToUpper();
bool equals = string.Equals(a, b, StringComparison.CurrentCulture);
// ✅ カルチャー非依存(どの環境でも同じ結果)
string upper = text.ToUpper(CultureInfo.InvariantCulture);
bool equals = string.Equals(a, b, StringComparison.Ordinal);
カルチャー依存のメソッド例
| メソッド | 問題点 | 対策 |
|---|---|---|
ToUpper() / ToLower()
|
トルコ語のI問題など |
ToUpperInvariant() を使用 |
string.Compare() |
比較結果が変わる |
StringComparison.Ordinal を指定 |
DateTime.Parse() |
フォーマット依存 |
CultureInfo.InvariantCulture を指定 |
単体テストでの注意点 🧪
// カルチャーを意識した単体テストの例
[Theory]
[InlineData("ja-JP")]
[InlineData("en-US")]
[InlineData("")] // Invariant Culture
public void DateFormat_ShouldBeConsistent_AcrossCultures(string cultureName)
{
// Arrange
var culture = string.IsNullOrEmpty(cultureName)
? CultureInfo.InvariantCulture
: new CultureInfo(cultureName);
Thread.CurrentThread.CurrentCulture = culture;
// Act & Assert
var date = new DateTimeOffset(2025, 12, 24, 0, 0, 0, TimeSpan.Zero);
var result = date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
Assert.Equal("2025-12-24", result); // どのカルチャーでも同じ結果
}
認証・認可における考慮事項 🔐
モダナイゼーションの際、認証・認可の仕組みも見直しが必要です。
古いイントラシステムの課題
| パターン | 問題点 |
|---|---|
| 🔓 IPアドレスベースの認証 | クラウドでは通用しない |
| 🔓 社員番号のみでログイン | パスワードなし = 認証ではない |
| 🔓 Windows認証のみ | Azure環境では追加対応が必要 |
| 🔓 独自セッション管理 | セキュリティリスク |
モダンな認証・認可へ移行
クラウド環境では、以下のような標準的な認証・認可の仕組みを採用しましょう。
| 方式 | 説明 | Azureサービス |
|---|---|---|
| 🔐 Microsoft Entra ID | 企業向けIdP(旧Azure AD) | Microsoft Entra ID |
| 🔐 OAuth 2.0 / OIDC | 標準的な認証プロトコル | Easy Auth, MSAL |
| 🔐 マネージドID | サービス間認証 | Managed Identity |
App Serviceの認証オプション
App ServiceではEasy Auth(組み込み認証) が利用できます。
- ✅ コードを変更せずに認証を追加可能
- ✅ Microsoft Entra ID, Google, Facebook等に対応
- ✅ トークン管理が自動化
// Easy Authを使った場合、ヘッダーからユーザー情報を取得
public class UserService
{
public string GetCurrentUserId(HttpRequest request)
{
// Easy Authが設定されている場合
return request.Headers["X-MS-CLIENT-PRINCIPAL-ID"].FirstOrDefault()
?? throw new UnauthorizedException();
}
}
認可の設計
| レベル | 実装方法 |
|---|---|
| 🎯 APIレベル |
[Authorize]属性、ポリシーベース認可 |
| 🎯 データレベル | Row-Level Security、フィルタリング |
| 🎯 UIレベル | 権限に基づく表示制御 |
まとめ
ASP.NETアプリケーションのモダナイゼーションにおけるインフラ選定のポイントをまとめます。📝
🎯 ベースライン構成
モダナイゼーションのベースラインとして、以下の構成を推奨します:
| カテゴリ | 推奨サービス | 理由 |
|---|---|---|
| 🖥️ コンピューティング | App Service | PaaS、運用負荷最小 |
| 🗄️ データベース | Azure SQL Database | フルマネージド、SQL Server互換 |
| 📁 ソース管理・CI/CD | GitHub | Copilot統合、VNetランナー対応 |
🎯 選定の基本方針
- PaaSを第一選択として検討する
- App Serviceをまず検討し、要件に合わない場合に他を検討
- ステートレス設計を前提にアーキテクチャを考える
- セッションや状態はAzure Managed Redisなどに外部化
- データベースはAzure SQL Databaseを第一選択
- DevOpsはGitHub + GitHub Actionsでシンプルに
- UTCベースで時刻を扱い、表示時にJST変換
- カルチャー非依存のコードを心がける
📊 サービス比較まとめ
| カテゴリ | 第一選択 | 代替選択肢 |
|---|---|---|
| 🖥️ コンピューティング | App Service | Container Apps, AKS |
| 🗄️ データベース | Azure SQL Database | SQL Managed Instance |
| ⚡ キャッシュ | Azure Managed Redis | - |
| 📁 ソース管理 | GitHub | Azure Repos |
| 🔄 CI/CD | GitHub Actions | Azure Pipelines |
🚀 次のステップ
モダナイゼーションは一朝一夕で完了するものではありません。以下のステップで進めていくことをお勧めします:
- 📖 学習 - Azure CAF、アーキテクチャセンターを読む
- 🔍 現状分析 - 既存アプリの依存関係、状態管理、時刻処理の洗い出し
- 🛠️ DevOps整備 - GitHub + GitHub Actionsでパイプライン構築
- 🔐 認証見直し - Microsoft Entra IDへの移行検討
- 🧪 PoC - 小規模なアプリでApp Serviceへのデプロイを試す
- 📋 計画 - 段階的な移行計画の策定
- 🚀 実行 - CI/CDパイプラインを活用しながら移行
🗺️ 全体構成イメージ
開発環境
| コンポーネント | 説明 |
|---|---|
| 💻 VS Code + Copilot | 開発IDE |
| 🔄 GitHub Actions | CI/CDパイプライン |
| 🤖 GitHub Copilot | AI開発支援(必須!) |
⬇️ CI/CDでデプロイ
Azure環境
| コンポーネント | 説明 |
|---|---|
| 🌐 App Service | Webアプリケーション |
| 🗄️ Azure SQL Database | データベース |
| ⚡ Azure Managed Redis | キャッシュ |
| ⚙️ Azure Functions | バッチ/イベント処理 |
💡 忘れずに対応すること
| 項目 | 対応内容 |
|---|---|
| 🕐 タイムゾーン | UTCベース設計、DateTimeOffset使用 |
| 🌍 カルチャー | Invariant Culture対応、テスト実施 |
| 🔐 認証 | Microsoft Entra ID移行 |
| 📊 状態管理 | ステートレス化、Redis外部化 |
モダナイゼーションの旅は長いですが、一歩ずつ進めていきましょう!
この記事がお役に立てば幸いです。
ご質問やフィードバックがあれば、コメントでお知らせください!
Discussion