AZ-204 メモ

Data Collector API
Azure Monitorへデータを入力するためのもの。
非推奨になっており、現在はログ インジェスト APIを使う
仮想マシン
スケールセット
負荷に応じたVMインスタンスの増減やロードバランサーの作成の自動化など、仮想マシンのリソースの自動管理ができるサービス
カスタムのスクリプト拡張機能
Azure仮想マシン上でスクリプトをダウンロードして実行。この拡張機能は、デプロイ後の構成、ソフトウェアのインストール、その他の構成などの管理タスクに便利。
VMの一般化
VMのイメージを作成するために、特定のVMインスタンスに固有の情報を削除し、そのイメージを再利用可能な状態にすること。例えば、"システム固有のデータの削除"などが含まれる。
- 【前提】VMは事前に定義されたイメージを元に作成できる。イメージをカスタマイズすれば事前にインストールさせておきたいソフトウェアなどをインストール済みの状態でVMを作成できる。これは複数のメンバーでVMを共有したいケースや迅速にVMを展開したい場合に便利
- VMイメージの一般化とカスタマイズ操作にはPowerShellを使用するのが一般的
- VMのイメージはBlob Storageに保存可能

Azure CDN
Azure Content Delivery Network (CDN) includes four products:
Azure CDN Standard from Microsoft
Azure CDN Standard from Akamai
Azure CDN Standard from Edgio (formerly Verizon)
Azure CDN Premium from Edgio (formerly Verizon).
CDNプロファイルとは
- CDNの設定やポリシーの集まり
- 具体的には、キャッシュの動作やセキュリティの設定など
- POPの数や位置を制御することはできないが、POPがどのようにキャッシュサーバとして動作するかは設定できるということ
Azure CDNのキャッシュのTTL
既定は以下のとおり
- 一般化された Web 配信の最適化: 7 日
- 大きなファイルの最適化: 1 日
- メディア ストリーミングの最適化: 1 日
キャッシュの動作
- キャッシュのバイパス: キャッシュを行わず、もともと指定されているキャッシュディレクティブ ヘッダーを無視します。
- オーバーライド: もともと指定されているキャッシュ期間を無視し、代わりに指定したキャッシュ期間を使います。 この設定では、キャッシュ制御 (キャッシュなし) はオーバーライドされません。
- 存在しない場合に設定: キャッシュ ディレクティブ ヘッダーがもともと指定されていた場合はそれに従い、指定されていなかった場合は、設定したキャッシュ期間を使います。キャッシュ ディレクティブ ヘッダーが設定されているかどうかであり、他のキャッシュ規則が存在しない場合ではないので注意。
キャッシュディレクティブヘッダ
Webサーバがブラウザや他のキャッシュシステムに対して、コンテンツのキャッシュ方法を指示するために使用するHTTPヘッダーのこと。
例えば、Cache-ControlやExpiresがある。
- Cache-Control: max-age=3600:リソースが3600秒(1時間)の間キャッシュされる
- Cache-Control: no-cache
- キャッシュは行うが、キャッシュ再利用前にオリジンサーバ側に「このデータは最新か?」という確認を実施する。そのため、データが最新であることが保証される。結局、オリジンサーバへの通信は発生するが、実際のデータを通信する必要がないため効率が良い。
- Cache-Control: no-store:キャッシュを全くしない
- Expires: Wed, 21 Oct 2025 07:28:00 GMT
クエリ文字列がある場合のキャッシュの動作
クエリ文字列による Azure CDN キャッシュ動作の制御
X-Cache
コンテンツがキャッシュされてCDNから提供されているのか、オリジンから提供されているのかなどが分かる。

Azure Event Hub
1スループットの単位
1 MB per second or 1000 events per second

Cosmos DB
最大ストレージサイズ
コンテナあたりの最大ストレージは、無制限
料金
- RU/sと使用されたストレージで料金が決まる
トリガー
CosmosDBのトリガーを使うことで、CosmosDBのコンテナに変更が入る前や後に任意のJavaScript処理を実行できる。
// Cosmosの初期設定時になどに下記を実行すると、
// 指定したCosmosのコンテナに特定の変更(TriggerOperationで指定)が入ったことを検知し、特定のタイミング(TriggerTypeで指定)でBodyに指定したJavaScriptコードを実行する
await client.GetContainer("database", "container").Scripts.CreateTriggerAsync(new TriggerProperties
{
Id = "triggerId",
Body = File.ReadAllText("path/to/trigger.js"),
TriggerOperation = TriggerOperation.Create, // Create, Replace, Delete
TriggerType = TriggerType.Pre // Pre or Post
});
composite index(複合インデックス)
CosmosDBにおいて、複数のプロパティを組み合わせたインデックスのこと。
"compositeIndexes":[
[
{
"path":"/name",
"order":"ascending"
},
{
"path":"/age",
"order":"descending"
}
]
]
とした場合、下記のケースにインデックスが効力を発揮する
-- 指定した順序と完全に一致
ORDER BY c.name ASC, c.age DESC
-- 指定した順序と全てが逆の順序
ORDER BY c.name DESC, c.age ASC
パーティションキーとは
役割
- データベース内を論理的に分割するためのもの
- 論理的に分割されることで、データ管理やアクセス効率が向上する
- 論理的な分割であり、パーティションごとに物理的に別のパーティションが作成されるわけではない
- Cosmos DBでは、内部的に複数のデータアイテムを含むパーティションが存在している
どのように分割されるか
- 多くの分散データベースでは、パーティションキーの値に基づいてハッシュ関数を適用する。そして、その結果に基づいてデータを特定のパーティションに割り当てる
より良いパーティションキー
- 均等に分割されるような値がパーティションキーになると良い
- 例えば、10万件のデータがあるとする
- A 95,000 / B 2,000 / C 2,000 / D 1,000となり、Aにデータが偏るのは良くない
- パフォーマンス / 一部のパーティションのみ負荷大 / スケールアウトやスケールアップが困難
- A 25,000 / B 25,000 / C 25,000 / D 25,000 となっているの方が理想的
- A 95,000 / B 2,000 / C 2,000 / D 1,000となり、Aにデータが偏るのは良くない
- 例えば、10万件のデータがあるとする
- 例えば、購入テーブルにおけるcustomerIdなど
- 顧客ごとにパーティションが論理的に分割されるので、適度に分散されていると言える
- 要するに、パーティションキーは一意である必要はないということ
合成パーティションキー
1つの値では適切な分散が得られない場合、2つ以上の値を合成してキーを作ることもできる(合成パーティションキー)。例えば、顧客IDだけではデータが偏ってしまうような場合、日付を後につけた文字をパーティションキーにするなど。

Azure SQL Database
Advanced Threat Protection
データベースへのアクセスや悪用を試みる、通常とは異なる、害を及ぼす可能性がある異常なアクティビティが検出される。
- SQL インジェクションの可能性
- 通常とは異なる場所またはデータ センターからのアクセス
- 通常とは異なるプリンシパルまたは有害な可能性があるアプリケーションからのアクセス
- SQL 資格情報に対するブルート フォース攻撃(総当たり攻撃)
Always Encrypted
- Azure SQL Databaseに保存された機密データを保護する機能。
- データベース管理者やクラウドサービスプロバイダなどのDB管理権限を持つ人が生の機密データにアクセスできないように常時暗号化を行う。
- データはクライアント側で暗号されて、その状態でDBに保存される。また、暗号化キーにアクセスできるクライアントによってのみ暗号化解除可能。つまり、復号化も暗号化もクライアント側で実施するため、DB管理側は生データにアクセスできない。
- 暗号化キーは、Key Vaultなどに保存される
- 暗号化と復号化にはそれなりのコンピュートリソースが必要なため、パフォーマンスに影響が出る可能性がある

Web ジョブ
- バックグラウンドタスクを実行するためのサービス
- Azure App Serviceの一部として提供される機能
対応言語

Azure Service Bus
"Service Bus キュー"と"トピック&サブスクリプション"は、Azure Service Busサービスの中の別の機能。
両者の主な違いは、以下の通り。
- Service Bus キュー:1つの送信者(プロデューサー)から1つの受信者(コンシューマ)へのメッセージ配信を行う
- トピックとサブスクリプション:トピックは複数のサブスクリプションを持つことができ、より複雑なメッセージ配信を実現できる
Service Bus キュー
1つの送信者(プロデューサー)から1つの受信者(コンシューマ)へのメッセージ配信を行うタイプのメッセージング機能を提供するサービス。単純な1対1のやり取りに適している。
Service Bus キューの主な特徴
- 受信側が受信する準備ができるまでメッセージを保持する
- 受信側は、キューに追加された順番でメッセージを受信して処理できる
- 送信側と受信側は同時にメッセージを送受信しなくて良い(非同期)
- 受信側は、その能力に応じてメッセージを受け取るタイミングや量を決められる(負荷平準のメリットがある)
トピックとサブスクリプション
パブリッシュ/サブスクライブ(Pub/Sub)モデルに基づいたメッセージング機能を提供するサービス
パブリッシュ/サブスクライブ(Pub/Sub)モデルとは
送信者(Publisher)と受信者(Subscriber)の間でメッセージがやり取りされる方法の1つのこと。
特徴としては、
- 送信者(Publisher)と受信者(Subscriber)が直接繋がっていないこと。つまり、送信者は直接受信者に送信せず、間にメッセージングシステムを挟む(Service Busで言うトピック)。
- 受信者(Subscriber)を容易に増やせるので、拡張しやすい
- 受信者(Subscriber)が自分に関連するトピックのみ選択して受信できる
- 受信者側の都合で受け取ることができ、それまではメッセージングシステム側にメッセージが保持されるため、受信者と送信者が同時にオンラインである必要がない(非同期)
トピックとは
- プロデューサー(送信者)がメッセージを送信する場所
- ここに集まったメッセージが各サブスクリプションに送信される。
サブスクリプション
- トピックに紐付く受信ルールや設定の集まりのことを指す(サブスクリプション = 受信者ではない)
- トピックとサブスクリプションの関係は、1:Nの関係。
- それぞれのサブスクリプションは、個々のフィルタリングルールや処理ロジックを持てる
- 実際にメッセージを受け取るコンシューマは、サブスクリプションを通じてメッセージを受け取る
PeekLock 受信モード
At-Least-Once メッセージ処理
ReceiveAndDelete 受信モード
At-Most-Once メッセージ処理
メタデータ
Azure Service Busのメッセージには、ペイロード(実際にやり取りされるデータ)とメタデータの2つがある。
CorrelationId
- メッセージ間の関連付けを行うためのID
- 例えば、特定の取引に関するメッセージには同じCorrelationIdを付けておき、後で追跡できるようにするなどして使う
- ユーザー側で自分で設定するもの
DeliveryCount
- 該当のメッセージが何回配信試行されたかのカウント
SequenceNumber
- 各メッセージごとに一意な値
- キューやトピックごとに一意な値
- メッセージが生成された順序を示す
- Service Bus側で自動的に付与されるもの
ReplyTo
- 受信側がメッセージに対して何かしらの応答をする必要がある場合、あらかじめこのプロパティに応答先を指定しておく。
ReplyToSessionId
- 受信側からの応答がリクエスト(メッセージ)と同一のセッションであるかを確認するためのもの。
トピックとサブスクリプションサンプルコード
using System;
using System.Threading.Tasks;
using Azure.Messaging.ServiceBus;
using Azure.Messaging.ServiceBus.Administration;
namespace MessageReader
{
public class Program
{
private const string ServiceBusConnectionString = "your_service_bus_connection_string";
private const string TopicName = "your_topic_name";
private const string SubscriptionName = "your_subscription_name";
static ServiceBusClient client = default!;
static ServiceBusProcessor processor = default!;
static async Task MessageHandler(ProcessMessageEventArgs args)
{
string body = args.Message.Body.ToString();
Console.WriteLine($"Received: {body}");
await args.CompleteMessageAsync(args.Message);
}
static Task ErrorHandler(ProcessErrorEventArgs args)
{
Console.WriteLine(args.Exception.ToString());
return Task.CompletedTask;
}
static async Task Main()
{
client = new ServiceBusClient(ServiceBusConnectionString);
// 特定のサブスクリプションを操作するClientを作成する
var administrationClient = new ServiceBusAdministrationClient(ServiceBusConnectionString);
var subscriptionDescription = new CreateSubscriptionOptions(TopicName, SubscriptionName);
// SQLフィルター
var sqlFilter = new SqlRuleFilter("MessageType = 'important'");
var ruleOptions = new CreateRuleOptions("ImportantMessageFilter", sqlFilter);
// フィルターは、サブスクリプションごとに指定する
await administrationClient.CreateSubscriptionAsync(subscriptionDescription, ruleOptions);
// サブスクリプション(受信者)
processor = client.CreateProcessor(TopicName, SubscriptionName, new ServiceBusProcessorOptions());
try
{
// 新しいメッセージを受信したときに呼び出すハンドラを登録
processor.ProcessMessageAsync += MessageHandler;
// 処理中にエラーが発生した場合に呼び出すハンドラを登録
processor.ProcessErrorAsync += ErrorHandler;
// イベントハンドラに登録したMessageHandlerを非同期実行
await processor.StartProcessingAsync();
Console.WriteLine("Waiting for messages...");
Console.ReadKey();
// メッセージの受信停止と終了処理
Console.WriteLine("\nStopping the processor...");
await processor.StopProcessingAsync();
Console.WriteLine("Stopped receiving messages");
}
finally
{
await processor.DisposeAsync();
await client.DisposeAsync();
}
}
}
}
サブスクリプションのフィルター
サブスクリプション(メッセージ受信者)ごとにフィルターを指定して、受信したいメッセージを選別できる。
フィルターには相関関係フィルターとSQLフィルターがある
- 相関関係フィルター:比較的単純な条件の時しか使用できないが、パフォーマンスに優れている
- SQLフィルター:相関フィルターと比べるとパフォーマンスは劣るが、AND OR NOT 条件や比較演算子を用いたより複雑な条件でフィルターできる
// 相関関係フィルターのサンプル
using Azure.Messaging.ServiceBus;
using Azure.Messaging.ServiceBus.Administration;
// Service Bus接続文字列とトピック、サブスクリプションの名前
string connectionString = "<your_connection_string>";
string topicName = "<your_topic_name>";
string subscriptionName = "<your_subscription_name>";
// ServiceBusClient と ServiceBusAdministrationClient のインスタンス化
var client = new ServiceBusClient(connectionString);
var adminClient = new ServiceBusAdministrationClient(connectionString);
// 相関関係フィルターの作成
var correlationFilter = new CorrelationRuleFilter
{
Label = "FinanceReport",
ApplicationProperties =
{
{ "Department", "Finance" }
}
};
var ruleName = "FinanceReportFilterRule";
var ruleOptions = new CreateRuleOptions(ruleName, correlationFilter);
// フィルタールールをサブスクリプションに適用
await adminClient.CreateRuleAsync(topicName, subscriptionName, ruleOptions);

App Serivce
カスタムドメイン
- Aレコード:App ServiceのIPアドレスとカスタムドメインを紐づける
- CNAMEレコード:App Serviceのデフォルトドメインとカスタムドメインを紐づける
デプロイ
Portalからデプロイはできない
App Service Environment
- シングルテナント
- App Serviceのプレミアムプランで、完全に分離された専用の環境が用意される
- 大規模かつセキュリティが求められるアプリケーション用
スケールアウト
Free と Shared のレベルではスケールアウトできない。
スケールアウトは、Standard以降のプランで利用可能。
プラン
共有コンピューティング: Free と Shared
- 他のユーザーのアプリとVMを共有する
- スケールアウトができない
- カスタム ドメイン用の Secure Sockets Layer (SSL) 証明書は使用できない
専用のコンピューティング: Basic、Standard、Premium、PremiumV2、PremiumV3 の
- 専用のVM上でアプリが稼働する
- ネットワークは他のユーザーと共有する
- カスタム ドメイン用の Secure Sockets Layer (SSL) 証明書の使用可能
- 自動スケールが必要な場合はStandard以降を使用する(Azure App Service での自動スケーリング)。Basicは手動スケールのみ。
Isolated
- 専用のVMに加えて、ネットワークも専用の仮想ネットワークが用意される
- ネットワークも他のユーザーのアプリと分離できる
ログ
- アプリケーションのログ記録(重大、エラー、警告、情報、デバッグ、トレースのあれ)
- デプロイ ログ
下記はwindowsアプリのみ - Webサーバのログ(生 HTTP 要求データ)
- 詳細なエラー ログ記録(クライアントのブラウザーに送信された .html エラー ページのコピー)
ログの保存場所
- ファイル システム
- Blob
の2種類が選択できる。
ファイル システム オプションは、一時的なデバッグ用であり、12 時間で自動的にオフになります。 Blob オプションは、長期的なログ記録用であり、ログを書き込む BLOB ストレージ コンテナーが必要
デプロイスロット
- Standard、Premium、または Isolatedで利用できる
- デプロイスロットは、固有のホスト名を持つアプリ
- 運用スロットとデプロイスロットをスワップすることで運用していく。スワップをすることでダウンタイムなしにリリースを実現できる(ブルーグリーンデプロイ)
デプロイ中のファイルロック
- Azure公式のデプロイでは、アプリの /home/site/wwwroot フォルダー内のファイルに変更が加わる。 そして、アプリの実行でもそれらのファイルが使用される。そうすると、デプロイ中にファイルロックが発生し、デプロイが失敗に終わる可能性がある。
- そこで、以下のような手段を取るべし
- アプリケーションを一時的に停止してデプロイする
- デプロイスロットを使ってデプロイする(スワップによって本番環境にデプロイする)
- スワップは、性質上、一度に実行され途中で失敗しないように設計されている。
- また、途中でファイルが書き換えられるようなこともない
スワップ前のアクション
<system.webServer>
<applicationInitialization>
<add initializationPage="/" hostName="[app hostname]" />
<add initializationPage="/Home/About" hostName="[app hostname]" />
</applicationInitialization>
</system.webServer>
applicationInitializationにはアプリケーションが起動する際に読み込むべきページを指定する。スワップ操作時はこのカスタムウォームアップを待ってからターゲットスロットとのスワップが行われる。たとえば、スワップ前に事前にターゲットスロットの状態を確認したりする。
web.configとは
Microsoft の IIS (Internet Information Services) を使用するASP.NET アプリケーションで設定を管理するためのファイル。
スワップ前のアクション_その2
App Serviceでは、以下の環境変数を使用してスワップ操作の際のカスタムウォームアップを制御できる。
具体的には、スワップ時にWEBSITE_SWAP_WARMUP_PING_PATH
で指定したアプリケーションに対して、正常に動作しているかの確認が実施され、WEBSITE_SWAP_WARMUP_PING_STATUSES
で指定した内容に該当すれば、そのウォームアップは成功したと判断される。
WEBSITE_SWAP_WARMUP_PING_PATH
- スワップ前にAzureサービスによって呼び出されるアプリケーション内の特定のパスを指定する
- /api/warmup:APIだったり
- /Home/Index:アプリの特定のページだったり
WEBSITE_SWAP_WARMUP_PING_STATUSES
- ウォームアップリクエストが成功したと見なされる HTTP ステータスコードを指定する
- 200-299: 標準的なHTTP成功レスポンスを示すステータスコードの範囲。
- 200: 200のみを成功とみなす
- 200-204:特定の範囲のみを成功とみなす
ARR アフィニティ
- ARR(Application Request Routing)
- アフィニティ:親和性/同一性
ARRアフィニティを有効にすると、クライアントからのリクエストが常に同じサーバーインスタンスに送信される。一度セッションが始まると、同一セッション内では同一のサーバに接続が固定されるイメージ。セッション状態を保持するアプリケーションでは、ユーザーエクスペリエンスが高まる。
※ マルチインスタンス デプロイされている前提
ただし、スケールアウトが考えられる環境だと、リクエストが均等に分散されなくなり、一部のインスタンスに負荷が集中する可能性がある。デメリットも多いため、通常はOFFにしておくので良い。
マルチインスタンスデプロイ
アプリケーションが複数のサーバーインスタンスにデプロイされること。可用性を高めるために一般的に使用される手法。
ローカルキャッシュ機能
- この機能を有効にすると、アプリケーションのコンテンツがAzure Storageからローカルストレージにコピーされ、一時的にそのデータを使用する。
- ストレージへの依存度が下がり、アプリケーションのパフォーマンスや可用性向上に役立つ
ローカルキャッシュ機能を有効にするには、App Serviceの構成に以下を追加する
"WEBSITE_LOCAL_CACHE_OPTION": "Always",
"WEBSITE_LOCAL_CACHE_SIZEINMB": "MB単位の任意のサイズ"
groupMembershipClaims
アプリケーションマニフェストの1つ。
グループ情報を含むユーザー情報がこのアプリの認証において必要かを設定するためのもの。
アプリケーションマニフェストとは、アプリケーションの設定や機能を定義するJSON形式のファイルであり、EntraIDの「アプリの登録」で登録したアプリごとに設定できる。
Always on設定
- 通常、App Serviceは、一定時間アクセスがないと自動でスリープモードに入り、リソース消費を抑える。その状態だと、次回アクセスがあった際に再度アクティブ状態に戻るのに少し時間が掛かる(Functionsの従量課金プランのコールドスタートと同様)。
- Always onにしておくと、スリープモードに入らない。
- Standardプラン以上で設定可能
WEBSITE_RUN_FROM_PACKAGEの設定
WEBSITE_RUN_FROM_PACKAGE = 1
にすると、パッケージから実行できるようになる。
ZIP パッケージから Azure App Service のアプリを直接実行する
パッケージから実行するメリットは、
- デプロイとランタイムの間でファイル ロックの競合がなくなります。
- 常に、完全にデプロイされたアプリのみが実行されることが保証されます。
- 運用環境のアプリにデプロイできます (再起動が必要です)。
- Azure Resource Manager デプロイのパフォーマンスが向上します。
- 特に大規模な npm パッケージのツリーの JavaScript 関数の場合、コールド スタート時間を減らすことができます。
長時間のアプリケーションログの保存
Azure App Service でのアプリの診断ログの有効化
- ファイル システムへの保存:一時的なデバッグ用 / 12 時間で自動的にオフ
- Blobへの保存:長期的なログ記録用であり、ログを書き込む BLOB ストレージ コンテナーが必要
Easy Auth
- App Serviceが提供する組み込みの認証と認可の機能のこと
- Microsoft、Google、Facebook、Twitterなどの認証プロバイダを使う
Azure App Service および Azure Functions での認証と承認
X-MS-CLIENT-PRINCIPAL-NAME
X-MS-CLIENT-PRINCIPAL-NAMEは、App ServiceによってホストされたWebアプリやAPIがEasy Authを利用している時にHTTPリクエストヘッダに含まれているもの。
Easy Auth利用時:アプリ コードでユーザー クレームにアクセスする
Easy Auth認証のプロセス
- ユーザーがApp ServiceにホストされたWebアプリやAPIにアクセス
- ユーザーはApp Serviceに設定された認証プロバイダ(Microsoftアカウント、Googleなど)を使用してログイン
- ユーザーの認証が完了すると、App ServiceがX-MS-CLIENT-PRINCIPAL-NAMEなどのヘッダをリクエストに追加
- 認証が完了したリクエストをアプリケーション側に転送
- アプリケーションはヘッダに含まれる内容をもとにユーザー情報を扱うことができる
CORSの有効化
コンテナをホストする(カスタムドメインで)
前提コマンド
Web Appsは既に作成されている前提
#/bin/bash
appName = “WebApplication$random”
location= “WestUS”
dockerHubContainerPath = “WebApplication/publicweb.v1”
fqdn = “www.WebApplication.com”
デプロイ
az webapp config container set
--docker-custom-image-name $dockerHubContainerPath
--name $appName
--resource-group RG1
カスタムドメインを設定
az webapp config hostname add
--webapp-name $appName
--resource-group RG1 \
--hostname $fqdn

Azure Cosmos DB
整合性レベル
強固 / 有界整合性制約 / セッション / 一貫性のあるプレフィックス / 最終的
- 強固に近いほど、整合性レベルは高まるが、スループットは減少する
- 最終的に近いほど、整合性レベルは低下するが、スループットは向上する
一貫性のあるプレフィックス
データを読み取る際に、書き込んだ順番で参照できることが保証されている。
が、データの反映自体は遅れる可能性がある。
単調読み取りは保証しない。
なぜなら、
・13時:データベースAを参照(ver1.0)
・14時:データベースAを参照(ver2.0)
・15時:データベースB(レプリカ)を参照(ver1.0)
のケースのように、レプリカ間の同期が遅れて、同じクライアントが古いデータの状態を読み取る可能性があるから。
単調読み取り
データベースからデータを参照する際に、一度参照したデータよりも古い状態のデータを再度参照しないことが保証される特性
複数リージョン書き込み
Azure Cosmos DB を使用するアプリケーションで複数リージョン書き込みを構成する
- 「複数の書き込みリージョン」機能を使用すると、データは2つ以上の異なる地理的リージョンにレプリケーションされる
- これにより得られるメリットは以下
- 可用性が高まる
- ユーザーの書き込みや読み取りは一番近いリージョンのDBに対して行われる。このため、レスポンスが速くなる
複数リージョン書き込みではない場合
複数の書き込みリージョンが有効でない場合(デフォルト?)、シングルマスター環境が設定されている。
シングルマスターの場合、データの書き込みは一つのリージョン(プライマリリージョン)でのみ行われ、他のリージョンは読み取り専用となる。
複数リージョン書き込みの設定方法
- Azure Portalで「複数の書き込みリージョン」を有効にする
- Azure Cosmos DB を使用するアプリケーションで複数リージョン書き込みを構成する
using Microsoft.Azure.Cosmos.Table;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace AzureTableStorageExample
{
class Program
{
static async Task Main(string[] args)
{
// Storage アカウントとテーブルへの参照を設定
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("your_connection_string");
CloudTableClient tableClient = storageAccount.CreateCloudTableClient(new TableClientConfiguration());
CloudTable table = tableClient.GetTableReference("your_table_name");
// パーティションキーに設定されている項目で、Smithと一致するものを全て取得する条件
string filterCondition = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "Smith");
// テーブルクエリを作成
TableQuery<CustomerEntity> query = new TableQuery<CustomerEntity>().Where(filterCondition);
// クエリを実行し、結果を取得
TableContinuationToken token = null;
do
{
// TableQuerySegment
// Azure Table Storageからデータを取得する際に使用されるエンティティのコレクションを表すクラス
// Azure Table Storageはページングをサポートしており、一度に返却されるデータ量には上限がある&大きなデータセットは複数ページ(セグメント)に分割されて返却される
TableQuerySegment<CustomerEntity> segment = await table.ExecuteQuerySegmentedAsync(query, token);
// TableQuerySegmentのContinuationTokenがnullになるまで、このループが継続する
// nullになったら全てのセグメントが取得できたということになる
token = segment.ContinuationToken;
foreach (CustomerEntity entity in segment.Results)
{
Console.WriteLine($"Name: {entity.RowKey}, Email: {entity.Email}");
}
} while (token != null);
}
}
// 顧客エンティティの定義
public class CustomerEntity : TableEntity
{
public CustomerEntity() { }
public string Email { get; set; }
// 他の顧客関連のプロパティ...
}
}

Azure Blob Storage
- Blob名の最大サイズは1024文字
- メタデータをセットするにはPUT要求
アーカイブからのリハイドレートの方法は2種類
- Set Blob Tier 操作でBlob層の変更を行う(PortalやCLIから)
- アーカイブ済み BLOB をオンライン層にコピーする
- リハイドレートには優先度がある(標準優先度と高優先度)
Storageアカウントで静的Webサイトのホスト
- 既定ページとエラーページをWebホスティングコンテナにアップロード
- HTTPSでカスタムドメインにしたい場合は、Azure Front DoorかAzure CDNが必要
コンテナでサポートしているヘッダ
- Etag
- Last-Modified
Blobの種類
Premiumプランの場合、下記の種類のBlobを使い分けできる
ブロック BLOB
- 大量データを効率的にアップロードするように最適化されている
- データアクセス層のアーカイブ層は、ブロックBlobのみ使用可能
ページ BLOB
- ランダムな読み取りと書き込みの操作用に最適化されている。Azure のディスクに記録する
追加 BLOB
- ブロック BLOB と同様だが、後からデータを追加する操作に最適化されている(ログのようにひたすら末尾に追加していくようなケース)
変更フィード
MedatData
リース
特定のリソース(ファイルやDBのレコード)を一定期間、排他的に使用するための仕組み。下記はBlobでそれを実施するサンプルコード。
通常のBlob操作で意識する必要はないが、
- 排他的アクセスを保証したい(つまりこの期間は他の操作でBlobが更新されることを絶対に防ぎたい)
- 長期間の操作が想定されるケース
- トランザクション処理を実施したい
など、データの整合性をより精緻に保ちたいケースにおいて使用すると良い。
CloudBlockBlob src = null;
try
{
src = container.ListBlobs().OfType<CloudBlockBlob>().FirstOrDefault();
// AcquireLeaseAsyncにnullを指定する場合は無限リース
var id = await src.AcquireLeaseAsync(null);
var dst = container.GetBlockBlobReference(src.Name);
string cpid = await dst.StartCopyAsync(src);
await dst.FetchAttributeAsync();
return id;
}
catch (Exception e)
{
throw;
}
finally
{
if (src != null)
await src.FetchAttributeAsync();
if (src.Properties.LeaseState != LeaseState.Available)
// リースの解放
await src.BreakLeaseAsync(new TimeSpan(0));
}

Azure Functions
プラン
従量課金プラン
- デフォルトのプラン
- 自動的にスケーリングされる
- 関数が実行されている際のコンピューティング リソースに対してのみ課金
- Functionsのインスタンスは、受信イベントの数に基づいて動的に追加されたり、削除されたりする
- コールドスタートが発生する
最適なケースとしては、「コストを抑えたい」「使用量が不規則または予測不可能」な場合
コールドスタート
一定期間アイドル状態になった関数の実行に遅れが生じる現象。
以下の流れで発生する。
- 関数が一定期間アイドル状態になり、インスタンスがスケールインされシャットダウンする
- 新たなイベントが発生して関数がトリガーされる
- 新しいインスタンスが起動される必要があり、このプロセスには時間が掛かる
- 結果、関数が反応するまでの時間に遅れが生じる
Premium プラン
- 需要(受信リクエスト)に応じて自動的にスケーリング
- アイドル状態になってもインスタンスが稼働し続けるため、遅延なくアプリケーションを実行できる(コールドスタートが起きない)
- よりスペックの高いインスタンス
- VNetへの接続可能
最適なケースとしては
- 高い性能を求める場合
- コールドスタートを避けたい(常時利用可能としたい)場合
専用プラン
- スケーリング
- 自動スケールを使用する場合、従量課金やPremiumの方がベター
- 需要に応じてマネージドにスケーリングが行われるわけではない
- 自動スケーリングはサポートされているが、スケールアウトのルールや条件はユーザーで設定が必要
- 専用のAzure仮想マシン(VM)で動作する
- 常に稼働するインスタンスを使用するので、コールドスタートは発生しない
- VNetへの接続可能
最適なケースとしては、より細かくカスタマイズする必要がある場合
functions.json
- トリガーとバインドが含まれる
- 通常のC#プロジェクトの場合は、このファイルを明示的に作成する必要はなく、属性で指定するのが一般的。この属性を基にビルドプロセスの中で自動でfunction.jsonが作成される
- C# スクリプトや他のスクリプト言語は、ビルドプロセスを介して自動的に生成される機会がないため、function.jsonを自分で作って、トリガーやバインドを指定する必要がある
認証レベル
- Function
- Functionのキーでアクセスする
- Anonymous
- 誰でもアクセスできる
- 要するに、Functionsのキーが不要ということ
- admin
関数アプリのタイムアウト
- 従量課金プランは、デフォルト5秒 / 最大10秒
- PremiumやApp Serviceは、デフォルト30秒 / 最大無制限
- 上記設定に関わらず、HTTPトリガーの場合は最大230秒。これはAzure Load Balancerの制限によるもの。
処理時間の長いものはどうするか
- Durable Functions async pattern を使う
- 関数自体は早めにレスポンスを返して実際の処理は別に実施するなどの対策を取る
- HTTPトリガーで要求を受け取り、それをAzure Service Busキューに渡す。HTTPトリガー関数は、ここで応答を返す(時間の掛かる処理はここでは行わないため、高速にレスポンスできる)
- Service Busのキューによってトリガーされる別の関数で非同期で実施。HTTPトリガーと異なり、Queueトリガーの関数には230秒の制限はない(ただし、関数アプリは長時間処理には不向きのため別のリソースを検討するのも1つの手)
App Serviceプランのalways on機能

ACR(Container Registry)
プラン
- Basic / Standard / Premium
- 全てのプランで保存時の暗号化をサポートしている
geoレプリケーション
Premiumプランのみ
権限
- AcrImageSigner:イメージの署名の権限
イメージの署名とは?
- コンテナのイメージに対して署名を行うこと。
- そのイメージが信頼できるソースによるものであり、改ざんされていないことを確認できる
- 作成者の意図通りであることが保証され、無許可や悪意のある変更から保護できる
ACRの認証
CI/CD パイプラインにイメージのプッシュを組み込む場合の認証は、
- AD サービス プリンシパル
- Azure リソースのマネージド ID
- CI/CD を実行するリソースのマネージド ID を作成し、そのマネージドIDに対してACRへのイメージプッシュ権限を付与する。
のいずれかを使用する必要がある。

Azure Cache for Redis
Redisモジュール
- Redisの機能を拡張するためのもの
- 例えば、フルテキスト検索などの高度な検索機能をRedisに提供するRediSearchなど。
Redisモジュールが使えるのは、エンタープライズプラン。
キャッシュの削除ポリシー

Microsoft ID
Web API にアクセスするようにクライアント アプリケーションを構成する
アクセス許可の種類
クライアントアプリケーションがMicrosoftの認証基盤を使用して、WebAPIにアクセスする時、以下の2種類のアクセス許可方法がある。
委任されたアクセス許可
- アプリがユーザーからアクセス許可を委任され、特定のアクションを行う
- Microsoftサービスにログインするときなど
アプリ専用アクセス許可
- ユーザーの介入なしにアプリケーションが特定のサービスにアクセスするために使用

App Service for Containers
通常、App Service for Containersはステートレスであり、コンテナ内のデータはコンテナのライフサイクルと同じとなる(コンテナが消失すればデータも消失する。再起動ごとにデータは消失する)。
WEBSITES_ENABLE_APP_SERVICE_STORAGE=true
DIAGDATA=/home
WEBSITES_ENABLE_APP_SERVICE_STORAGEをtrueにすると、App Serviceの特定のディレクトリがコンテナにマウントされる。これによって、データを永続化できる。
具体的には、Azure App Serviceの/homeディレクトリが持続性ストレージのルートとして機能する。

Application Insights
- Webアプリやサイトをデプロイした後、定期的なテストを実施して、可用性や応答性を監視できる。
- 例えば、世界中の各ポイントからアプリにリクエストを送信して、応答がない場合や遅い場合はアラートを出したり。
テストには以下のものがある。
テスト自体は、自分自身でデプロイしたものだけではなく、自身のアプリケーションが依存している第三者APIなどを対象とすることもできる。
Log Analyticsとの違い
- Application Insightsはアプリケーションレベルでのパフォーマンス管理と使用状況トラッキングに特化している
- 可用性、パフォーマンス、ユーザーの操作など、アプリケーションレベルでの問題を診断するために使用する
- Log Analyticsは、Azure環境やオンプレミスも含めたより広範なデータを集約し、分析するもの。アプリケーション以外のログも対象となる。
影響分析
ロード時間やその他のプロパティがアプリのさまざまな部分のコンバージョン率にどのように影響するかを分析
ユーザー、セッション、イベント
「ユーザーが Web アプリをいつ使い、どのページに最も興味があり、ユーザーがどこにいて、どのようなブラウザーやオペレーティング システムを使っているか」
ファネル(Funnels)
ファネル:Web アプリケーション内の一連の手順の進行
ユーザーが特定の目標(例えば、商品の購入、サインアップなど)に到達するまでの各ステップの完了率を把握できる。これによって、どのステップでユーザーが離脱しているかなどが分かる。
ユーザーフロー
ユーザーがサイトのページや機能の間をどのように移動するかを視覚化
保持(Retention)

API Management
バックエンドAPIと安全に通信するため、APIManagement側でクライアント証明書を設定可能。
この場合のクライアントは、APIManagement自体。
ゲートウェイ認証にクライアント証明書を使用するように API を構成する
ポリシーのサンプル
<policies>
<!-- APIManagementに到達したクライアントからのリクエストを処理するために使用される -->
<!-- 目的は、入ってくるリクエストを検証&変換し、リクエストに対してポリシーを適用すること -->
<inbound>
<rate-limit calls="10" renewal-period="60" />
<!-- 他のインバウンドポリシー -->
</inbound>
<!-- バックエンドポリシー:APIリクエストがバックエンドサービスに送信される前に適用されるポリシーのセット -->
<backend>
</backend>
<outbound>
<set-header name="X-Powered-By" exists-action="delete" />
<set-header name="X-AspNet-Version" exists-action="delete" />
<base />
</outbound>
<on-error>
<!-- エラーハンドリングポリシー -->
</on-error>
</policies>
<inbound>と<backend>の違い
バックエンドサービスに送信される前に処理されるという点では共通している。
どのような使い分けがされるのか。
inbound
- 入ってくるリクエストを検証&変換し、リクエストに対してポリシーを適用することが目的
- ゲートウェイにリクエストが到着した直後(バックエンドAPIに送信される前)に処理される
- ゲートウェイに到着した全てのリクエストに対して、同じ処理を行う
- backendのように、特定のバックエンドAPIを対象とすることはできない。あくまで共通処理。
backend
- 複数のバックエンドAPIがある時、特定のバックエンドAPIのみを対象としたリクエスト処理を実施できる
- inboundポリシーの後、バックエンドAPIにリクエスト送信される直前
API Managementのインポート
- OpenAPI(旧Swagger)などで定義されたAPIファイルをAPI Managementサービスに取り込むこと。APIMにAPIを取り込むとそのAPIをAPIMで管理&公開できるようになる。
- 新しく取り込むだけではなく、既にAPIMに登録済みのAPI定義を修正する場合も
az apim api import
を使用する
az apim api import \
--resource-group myResourceGroup \
# APIMのサービス名
--service-name myAPIMService \
# API Management内でのAPIのベースパス
--path myapi \
# 取り込むAPIの定義ファイルの形式(例:OpenAPI、WSDL)
--specification-format OpenApi \
# 取り込むAPI定義ファイルのローカルまたは外部URLのパス
--specification-path /path/to/openapi.json
--pathに関する補足
例えば、商品(products)に関するAPIをAPIM(https://myapim.azure-api.net
)に追加する場合、
--path products
を付与すると、このコマンドで追加されたAPIのベースURLは、https://myapim.azure-api.net/products
となる。

Azure AD(Entra ID)でのアプリの登録
アプリケーションがAzureリソースに安全にアクセスするために、AzureADにアプリを登録することができる。
アプリの登録を実施すると、
- アプリからAzureリソースへのアクセス
- EntraIDがこのアプリに十分な権限(アクセスを試行したリソースへのアクセス権限があるか)があるかを確認し、権限があれば、トークンを返却
- アプリはトークンを用いてリソースへアクセスする
という流れで安全にリソースへ接続できるようになる。
アプリの登録時、リダイレクトURLを登録する必要がある。
このリダイレクトURLは、Entra IDによる認証後にユーザーがリダイレクトされる先。
認証後にリダイレクトされる先なので、アプリケーションのURLを設定することになる。
当然だが、Azure ADに登録されたリダイレクトURLとアプリケーションが使用するURLは一致している必要がある。

ACI
az container logs
- 指定したACIのログを取得する
- アプリケーションのログも含まれるので、アプリケーションのトラブルシューティングに適当
az container attach
- 実行中の Azure コンテナー インスタンスにアタッチして、コンテナーの標準出力と標準エラー出力をリアルタイムで見ることができる
- 実行中の状態をリアルタイム監視するのに適当
コンテナの起動に時間がかかる場合

Entra ID
アプリケーションマニフェスト
Entra IDで登録したアプリ(アプリの登録から)の設定や構成を定義するJSONファイル。
Azure Portalでは登録済みのアプリのページで 管理 > マニフェスト から確認できる。
Implicit Flow
- OAuth 2.0プロトコルの一部
- 特にシングルページアプリケーション(SPA)などのブラウザベースのアプリケーションで使用される認証フロー
- アクセストークンがブラウザに返されるため、バックエンドサーバを介したトークン交換をしなくて済む
Implicit Flowの流れ
- ユーザーの認証
- 認証サーバ(Entra ID)にリダイレクトされて、ログインする
- アクセストークン取得
- 認証が完了すると、アクセストークンがブラウザに返される
- トークンは、リダイレクトURLに含まれる
- アプリケーションからのアクセス
- SPAなどのアプリは、このアクセストークンを使用して、APIなどのサーバへのアクセスを実施する

Service Bus / Event Hubs / Event Gridの比較
Service Bus
-
メッセージング機能
-
順番や信頼性が重要な場合に適当
-
プルベースのシステム。メッセージをキューかトピックに格納し、クライアント側がメッセージを取得しに行くスタイル。クライアント側の都合でメッセージを取得できるので負荷平準のメリットもある。
Event Hubs
- 大量のイベントデータの収集などに向いている
- 個別ユーザーへの通知などは不向き
Event Grid
-
軽量のイベントに適している。例えば、個別ユーザーへの通知など
-
イベントなので、一方的な通知であり、受信側からの反応は期待しない
-
プッシュベースのシステム。イベントが発生すると自動的にイベントサブスクリプションに登録済みの受信側に通知が行く。サブスクリプションで指定したエンドポイント(Webhook、Azure Function、Logic Appなど)が通知を受け取り、このイベントを処理する(受信側は通知を受け取ればよく、自分から取得に行く必要はない)

CallerIPs と IncomingIPs
Caller IPs
- 通信を開始するクライアントのIPアドレス。
- 典型的な事例としては、APIにリクエストを行うクライアントのIPアドレス
- API Managementでクライアント向けのAPIを公開している時に、IPアドレスによるアクセス制限を実施したいなら、このCaller IPsが対象となる
IncomingIPs
- サーバに到達するすべてのリクエストのIPアドレス(Caller IPsを含む概念)
- プロキシやロードバランサのIPアドレス
- クライアントが直接サーバにリクエストをするのではなく、ロードバランサなどの中間サーバを挟む場合、それらのIPアドレスも含む

Queue Storage
サンプルコード。
- QueueServiceClientがAzure Queue Storageを扱うもの
- QueueClientがストレージ内のQueueを扱うもの
- QueueMessageがQueueの中のメッセージを扱うもの
using Azure.Storage.Queues;
using Azure.Storage.Queues.Models;
using System;
using System.Threading.Tasks;
// Azure Storage Queueの接続文字列
string connectionString = "<your_connection_string>";
// 使用するキューの名前
string queueName = "sample-queue";
// QueueServiceClientのインスタンスを作成
QueueServiceClient serviceClient = new QueueServiceClient(connectionString);
// キューを作成(存在しない場合)
QueueClient queueClient = serviceClient.GetQueueClient(queueName);
await queueClient.CreateIfNotExistsAsync();
// メッセージをキューに送信
string message = "Hello, Azure Queue!";
await queueClient.SendMessageAsync(message);
// キューからメッセージを受信
QueueMessage[] receivedMessages = await queueClient.ReceiveMessagesAsync(maxMessages: 1);
if (receivedMessages.Length > 0)
{
QueueMessage receivedMessage = receivedMessages[0];
// 受信したメッセージを処理(ここではコンソールに出力)
Console.WriteLine($"Received message: '{receivedMessage.MessageText}'");
// メッセージをキューから削除
await queueClient.DeleteMessageAsync(receivedMessage.MessageId, receivedMessage.PopReceipt);
}
Queue Storage と Service Bus Queueの違い
- Service Bus Queueは順序保証(先入れ先出し (FIFO))がある
- Service Bus Queueの最大キューサイズは、80GB。80GBを超える場合はQueue Storageを検討する。

Azure Front Door
キャッシュ削除
- 単一パス消去: プロトコルとドメインを除きファイル拡張子を含む、アセットの完全なパスを指定して、個々のアセットを消去します。 (例: /pictures/strasbourg.png)。
- ルート ドメイン消去: パスに /* を付けてエンドポイントのルートを消去します。

Azure Functionsの並列処理
host.jsonの設定(batchSize)
{
"version": "2.0",
"extensions": {
"queues": {
"maxPollingInterval": "00:00:02",
"visibilityTimeout" : "00:00:30",
// Functions ランタイムが同時に取得して並列で処理するキュー メッセージの数
// 1 つのキューで受信した複数のメッセージの並列実行を回避したい場合は、batchSize を 1 に設定
"batchSize": 16,
"maxDequeueCount": 5,
"newBatchThreshold": 8,
"messageEncoding": "base64"
}
}
}
batchSizeは、Azure Queue StorageやAzure Service Bus QueueなどのQueueトリガーを使用する場合に使用される設定。
例えば、Queueトリガーによって発火するFunctionsでSQLデータベースにアクセスするケースがあるとする。その際、並列実行だとプールされた接続がすべて使用中のため接続タイムアウトになる可能性がある。そのような場合は、batchSizeの数をDBの最大プール・サイズ以下にする。
BlobTriggerやTimerTriggerの並列実行
- BlobTrigger
- 異なるBlobファイルに対しての複数Functionsインスタンスによる並列実行は行われるが、同一Blobファイルに対する操作は順次処理されるのが普通
- TimerTrigger
- 基本的にスケジュールに従って動くので、順次処理が普通(並列は避けるのが通常)。
Queueトリガーは、Functions側でも並列実行が想定されている。Queueに溜まったメッセージを並列で実行していくことはよくあるパターンだから(BlobやTimerと違って並列を避ける理由は一般的にはない)。

AzCopy
ストレージアカウントやコンテナ間でBLOBやファイルを効率良くコピーする方法

Event Grid
validationCodeハンドシェイク
Event Gridを使用する前に正しくイベントを受け取ることができるエンドポイント(主にwebhook)かを確認するプロセス
- イベントサブスクリプションの作成(イベントを受け取るWebhookエンドポイントのURLを指定する)
- サブスクリプションが作成(or更新)されると、自動的にEvent Gridからエンドポイントにバリデーションイベントが送信される(これにvalidationCodeが含まれている)
- エンドポイントはイベントを受け取り、validationCodeをEvent Gridに返送する
- ※ 通常、Event Gridのイベントを受け取る側は、何かを返却する必要はないが、この最初のバリデーションプロセスの際は受信側から返送するため双方向のやりとりが発生する
このプロセスを行うことで、実際のイベントが通知される前に下記を実現できる。
- 予期しないエンドポイントへイベントが配信されることを防ぐ
- エンドポイントの所有権の確認
- そのエンドポイントがEvent Gridのイベントを受信する意図と能力があることを確認する
[
{
"id": "2d1781af-3a4c-4d7c-bd0c-e34b19da4e66",
"topic": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"subject": "",
"data": {
"validationCode": "512d38b6-c7b8-40c8-89fe-f46f9e9622b6",
"validationUrl": "https://rp-eastus2.eventgrid.azure.net:553/eventsubscriptions/myeventsub/validate?id=0000000000-0000-0000-0000-00000000000000&t=2022-10-28T04:23:35.1981776Z&apiVersion=2018-05-01-preview&token=1A1A1A1A"
},
"eventType": "Microsoft.EventGrid.SubscriptionValidationEvent",
"eventTime": "2022-10-28T04:23:35.1981776Z",
"metadataVersion": "1",
"dataVersion": "1"
}
]
サブスクリプションスキーマ
Event Gridのサブスクリプションを設定するためのもの

Key Vault
Key Vaultに保存したカスタムキーを使用してBlobを暗号化するサンプルコード
通常、Blobはマネージドキーにより暗号化されているが、よりセキュリティを強化したい場合、業界標準の暗号化の規定がある場合など独自の暗号化キーを使い暗号化を行うことがある。
そのようなキーは通常Key Vaultに保存するのが一般的。
// KeyVaultKeyResolver: KeyVaultに格納されたキーを扱うためのセキュリティを兼ね備えた強化版Client的なもの
var resolver = new KeyVaultKeyResolver(_keyVaultClient);
// Azure Key VaultからRSAキーを取得します。このキーは暗号化に使用されます。
var rsa = resolver.ResolveKeyAsync(
"https://contosokeyvault.vault.azure.net/keys/TestRSAKey1",
CancellationToken.None).GetAwaiter().GetResult();
// 取得したRSAキーを使って、Blobの暗号化ポリシーを設定します。
BlobEncryptionPolicy policy = new BlobEncryptionPolicy(rsa, null);
BlobRequestOptions options = new BlobRequestOptions() { EncryptionPolicy = policy };
// アップロードするファイルのために、Blob Storage内の特定のブロブ(この場合は"MyFile.txt")を参照します。
CloudBlockBlob blob = contain.GetBlockBlobReference("MyFile.txt");
// ローカルファイル("C:\Temp\MyFile.txt")を開き、設定した暗号化ポリシーを使用してAzure Blob Storageにアップロードします。
using (var stream = System.IO.File.OpenRead(@"C:\Temp\MyFile.txt"))
blob.UploadFromStream(stream, stream.Length, null, options, null);
アクセスポリシーを設定する
az keyvault set-policy
--name <KeyVaultName>
--object-id <ObjectId>
--key-permissions wrapkey unwrapkey get