Azure ストレージを使用する時の考慮事項

カスタムドメインSSL は不可

Azure ストレージはカスタムドメインは使えるが、カスタムドメインSSL はサポートしていない。カスタムドメインSSL での HTTPS アクセスが必要な場合、CDN 経由で行う必要があるらしい。

BLOB ファイルに HTTP 経由でアクセスしたい場合、選択肢は基本的に以下 2 つになる。

参考

FTP による操作は不可

AzCopy コマンドでのファイル転送は出来るが、FTP は今の所サポートされていない。

参考

メタデータの使用が可能

ファイルの補足情報として、メタデータの付与が可能。プログラムでも利用できるので、メタデータを基に動的にファイル処理できる可能性が広がる。 ただ、ファイル上書きでもメタデータは消えてしまうのと、Azure Storage Explorer の一覧画面ではメタデータの内容を確認できない点などは注意する必要がある(1 ファイルごとにプロパティで確認は可能)。

参考

Entity Framework 使用時の注意点とか

EF 側

  • EF を利用するプロジェクトと同じプロジェクトに EF を含めることも可能だが、xxx.DAL みたいな名前の専用プロジェクトを新規に作成して、そちらで管理した方が良いかも(お好きな方で)
  • EF ライブラリは Nuget からインストールできる (Entity Framewok で検索すれば MS のが出てくる)。バージョンによって使える機能に結構差があるようなので、最新版を推奨
  • ライブラリをインストールしたら、当該プロジェクトに新しい項目を追加し、"ADO.NET Entity Data Model" を追加する
  • CodeFirst によるモデルから DB の更新もできるらしいが、自分は DB でスキーマ更新して、それを EF のモデルに反映させる派(お好きな方で)
  • モデル (edmx) を更新すると、edmx 配下の context.cs 等も自動更新されるので、これらのソースに直接手を加えるのは、NG (モデル更新時にこれらのファイルも初期化されるので)
  • edmx を更新した際、セキュリティテンプレートを更新するか的な確認ダイアログが表示されるが、これは全て「はい」を選ぶ。この処理で edmx 配下の自動更新ファイルが更新されるので、ここで更新拒否すると、不整合が発生する
  • edmx に一度不整合が発生した場合、edmx をエディタで直接開いて確認した方が良いかもしれない。例えばモデルの更新が正しく行えなかったりソース管理機能のマージで失敗すると、同じカラム名が edmx に重複定義されて、それが原因でモデルが表示できなくなったりしてしまうことがあるが、そうなると直接 edmx を確認したり、作り直したりする必要が出てくる
  • 上述したように、ソース管理機能のマージで失敗するとモデルのメタ情報が壊れて悲惨な目にあうので、EF プロジェクトのアイテムに関しては、マージ機能は使わない事を推奨。同時に複数人で更新しないとか、モデル更新するのは特定の人だけにするとかの運用が必要かと思われる。とにかく、マージは凄い勢いで壊れる。
  • Entities クラス名をかえたいとかであれば、edmx のエンティティコンテナー名とかで変更する必要がある
  • 名前空間も注意。特に他からコピーした時など
  • データアクセスのリトライ処理は自前で用意するのではなく、DbConfiguration で SetExecutionStrategy() を実行して、EF ライブラリ側で対応する。Azure SQL Database に接続しているのであれば、SqlAzureExecutionStrategy を使う。(接続の回復性と再試行ロジック)
  • 必ずしも DB の最新スキーマと常に同期させる必要はなく、プログラムから使用する DB リソースに関連する箇所が EF と同期されていれば、プログラムから EF を使う上では特に問題ない

EF 使う側

  • 接続先 DB は EF オブジェクト作る際に接続文字列を渡して、EF から DB を動的に切り替えられるようにする。こうすることで、アプリケーション設定の変更のみで dev, stg, prd など DB を切り替えることが出来る
  • EF オブジェクト作成時に接続文字列を渡して初期化させる件は、既定ではないので、EF 側に仕掛けを追加する必要がある。作成された DbContext クラスの Partial クラスを追加し、そちらで接続文字列を受け取り設定するコンストラクタを追加する (DbContext クラスを直接編集すると、前述したようにモデル更新時に初期化されて消えてしまうため)
  • DB 接続文字列は、EF 配置したプロジェクトの App.config に記載されているので、それを流用して使用する。Azure Web Apps や Functions 等であれば、アプリケーション設定に定義しておけばポータルから操作できるので、お手軽

Azure リソースの本番、開発用の使い分けについて

一般的なプロジェクトの開発からリリースまでの流れとして、

  1. ローカルや Azure 上の Dev 環境で開発
  2. Azure 上のステージング環境でテスト
  3. Azure 上の本番環境にリリース

となる事が多いと思うが(他知らないので、その前提で進めます)、このステップを踏む場合、Azure のリソースも基本的にはそれぞれのステージごとに用意する必要がある。 けど、Azure のリソースを使う場合この選択肢がいくつかあるので、どれを選択するかと言う話。

この話については、当該システムでどの Azure リソースを使うかにもよるので一概にこの方法でと言うのは言えないが、ここでは Web Apps を使ったシステムを例に考えてみる。

自分が考えつく各ステージごとのリソースの分け方としては、以下のような分け方がある。

基本的には、上に行くほどコストや手間がかかるがリソースとしては安定し、下に行くほどコストや手間がかからないがリソースとしては安定しない。 色々と考え方はあると思うが、個人的には、本番とそれ以外は、サブスクリプションを分けてしまった方が、ヒューマンエラーなども起こりづらく、色々すっきりすると思う。 それぞれの方法について、メリットとデメリットを挙げると、以下な感じ。

サブスクリプションで分ける
  • メリット
    • ヒューマンエラーが起こりづらい。特に、開発時に誤って本番リソースに対して変更等かけてしまうと言った間違いは起こりづらくなる
    • リソースが安定する。本番と開発でリソースが分かれているので、いくら開発で負荷かけたり不安定な状態になったとしても、本番には影響ない
    • 本番環境のスケールアップ・スケールアウトが、本番環境だけにフォーカスして検討・設定できる
  • デメリット
    • コストがかかる。開発用リソースは最低限のプランで用意するとしても、それなりのランニングコストを覚悟する必要がある
    • リソースの準備・メンテの手間がかかる
    • ダッシュボードなどを利用した本番リソースの日常の監視がしづらい (普段は開発用のサブスクリプションでしか作業していない場合)

App Service で分ける

  • メリット
    • ヒューマンエラーが起こりづらい。サブスクリプション毎わけるのに比べれば発生確率上がるが、Azure リソース自体は別なので、まだ起こりづらいと言えるレベル
    • リソースが安定する。本番と開発でリソースが分かれているので、いくら開発で負荷かけたり不安定な状態になったとしても、本番には影響ない
    • 本番環境のスケールアップ・スケールアウトが、本番環境だけにフォーカスして検討・設定できる
  • デメリット
    • コストがかかる。コスト面で見ると、サブスクリプション毎分けるのと大差ないレベル
    • リソースの準備・メンテの手間がかかる。これも、サブスクリプション毎分けるのと大差ないレベル。証明書のインストールなども、App Service 単位で必要

Web Apps で分ける

  • メリット
    • コストがかからない。本番・開発で同じ App Service を使う場合、料金は App Service 単位でかかるので、コストを節約することができる
    • ヒューマンエラーが起こりづらい。Azure ポータルで見た時の Azure リソースとしては別 Web Apps として分かれているので、基本的には App Service で分けるのと同様のレベル
  • デメリット
    • リソースが安定しない。本番・開発で同じ App Service を使う場合、利用可能な CPU、メモリリソースなども全 Web Apps で共有するため、開発用 Web Apps で生じた負荷などが、本番環境にも影響してしまう。例えば大量アクセス時の動作確認しようとして開発環境に負荷をかけると、本番環境も同様の負荷状況に陥ってしまう。逆も同じ
    • 本番環境のスケールアップ・スケールアウトが、本番環境だけにフォーカスして検討・設定できない(App Service 単位での設定になるため)

スロットで分ける

  • メリット
    • コストがかからない。本番・開発で同じ App Service を使う場合、料金は App Service 単位でかかるので、コストを節約することができる
    • スロットのスワップによるデプロイが利用できる
  • デメリット
    • ヒューマンエラーが起こりやすい。特に Web Apps は既定スロットを運用スロット(=本番スロット)として扱うことが多いと思うが、Azure ポータルで当該 Web Apps を開いた時に初期表示されるのが既定スロット(=本番スロット)である事が、ヒューマンエラー発生時のリスクの高さに拍車をかけている。仮に Dev, Prd を同一アプリのスロットで分けて開発する場合、開発中は相当注意して Azure ポータルで Dev スロットの操作を行う必要がある
    • リソースが安定しない。本番・開発で同じ App Service を使う場合、利用可能な CPU、メモリリソースなども全 Web Apps で共有するため、開発用 Web Apps で生じた負荷などが、本番環境にも影響してしまう。例えば大量アクセス時の動作確認しようとして開発環境に負荷をかけると、本番環境も同様の負荷状況に陥ってしまう。逆も同じ
    • 本番環境のスケールアップ・スケールアウトが、本番環境だけにフォーカスして検討・設定できない(App Service 単位での設定になるため)

個人的に思うところ

なるべくコストを低く抑えたいと言うのは普通どこでも最初に挙げる要望だと思う。ただ、メリットとデメリット、リスクとリターンのバランスを考慮する必要がある。 ヒューマンエラーの可能性とリソースの安定性、デプロイの影響、URL などの接続情報の分離、コストなどを総合的に鑑みた場合、自分としては以下のような選択肢が思い浮かぶ。

  • 開発環境の負荷や不安定さが本番環境にも影響を与えるのはよろしくない。これを優先して考慮すると、本番と開発は、少なくとも App Service を分ける必要がある。またこうすることで、本番インスタンスのスケールアップ・アウトもシンプルに設計することが可能
  • 本番へのリリースは、スロットのスワップで行いたい。これを考慮すると、本番及び、本番リリース前の動作確認用のステージング環境を、同じ Web Apps のスロットで分ける方法が良いかなと思う
  • 開発及び、開発よりのステージング(?)環境は、コストを考慮して同じ App Service または Web Apps に用意する
  • 可能であれば、本番系と開発系で、サブスクリプションを分けたい

異なるアプリの Azure リソース上の共存について

上述した内容は同じアプリの Dev, Stg, Prd 毎の扱いについてだが、やろうと思えば異なるアプリも同じような考えで同一リソースに共存することが可能。 ただ、異なるアプリを同一リソースで動作させる場合、最低でも、デプロイや URL、バックアップの単位などは他に影響ないように分けるべき。

例えば Web Apps に関して言えば、App Service プランを共有するのはギリギリいけるとしても、Web App リソースは完全に分けるべき。 Blob ストレージも、接続時の URL が同じで困るのであれば、ストレージ アカウントを分ける。 同様に DB も、DB コピーの単位がスキーマ単位なので、最低限スキーマ単位では分ける、など。

Azure AD アカウントのパスワード有効期限

Azure AD アカウントのパスワード有効期限は既定で 90 日。 どのようなポリシーを採用するかにもよるが、基本的には定期的にパスワード変更するよりかは無期限の方が良いと思われる。

Azure ポータルで無期限に変更することは今の所できないようで、変更するには Azure AD PowerShell モジュールのコマンドレットを使用する (端末へのモジュールインストールが必要)。 使用するコマンドレットは Set-AzureADUser (v2 用)。

参考 URL

Microsoft Teams で複数アカウントを同時に使う方法

注:Windows で使うときの話です

Microsoft Teams はデスクトップアプリもブラウザアプリも出ているが、どちらもアカウントは一つしか使えない。 使いたい Teams のアカウントが一つであれば問題ないが、複数アカウントを同時に使いたい時に困る事になるので、その時の対応方法。 なお、アカウントが一つであれば、動作が安定していて軽い、デスクトップアプリの使用を強く推奨。

対応方法

一つのアプリで一つのアカウントしか使えないのはもうどうしようもないので、デスクトップアプリとブラウザアプリを同時に使って、複数アカウントを同時に使う。

  1. まず、メインの Teams アカウントは、デスクトップアプリで使用する (上述したように動作が安定していて軽いので)
  2. 次に 2 つ目のアカウントは、IE でブラウザアプリを開いて使用する。この際、単純にブラウザで開いて使うとやや使いづらいので、ブラウザで Teams を開いた後、そのページをピン留めし (「ピン留め」を使って 1 クリックで Web サイトにアクセスする)、以降はピン留めから起動して使用する
  3. もし 3 つ目のアカウントもある場合は、IE を InPrivate ブラウズ モードで開き (IE を起動した後に Ctrl + Shift + P)、その状態で Teams を開いた後にピン留めして使用する。但し InPrivate モードの場合は Teams を開く際に毎回アカウントの入力が必要になるので、注意

その他考慮事項

  • IE は Teams 専用ぐらいに割り切って使用し、通常のブラウザ使用は Chrome とか FireFox とか、他のブラウザを使う方が問題起きづらいと思う。
  • ブラウザアプリ (InPrivate ブラウズじゃない方) はパスワードを保存しておくと毎回のログインが楽になるが、パスワード保存の確認が出てこない場合は、オートコンプリート履歴でパスワードを削除すれば、また確認が出てくると思う(IE11でユーザー名とパスワードが保存されなくなった時は2つの手法を試せ!)

リンク

Azure Functions で使用するログについて

Application Insights の使用

Azure Functions で使用するログとして一番簡単なのは、既定で使用可能な、Azure ストレージを使用する組み込みログ。 追加で必要な設定なども特に不要で、Azure ポータルからもすぐに確認できるので初めは便利だが、Azure ポータルで表示されない事も多々あり、サブやテスト的に使う以外はあまりお勧めできない。 メインのログとして記録・参照する必要があるのであれば、Application Insights (AI) の使用に切り替えるのをお勧めする。

AI も取りこぼしがなくてそこまで信頼性が高いかと言われると微妙なところだが、組み込みのログよりは全然マシ。 また、機能的にもライブ メトリック ストリームでリアルタイムに確認できたり、一般的な検索も Azure ポータルから簡単に行える。やろうと思えば、クエリによる検索も可能。

log4net ログの使用

AI でデバッグログやトレースログを含む大量のログ出力を行った事がないので、本当は AI 一本でも可能なのかもしれないが、大量に出力される可能性があるデバッグ系ログは、今のところ自分は log4net を使用したファイル出力で対応している。 通常のログファイルとしてダウンロードしてエディタで見れるので、誰でも直感的に確認しやすい。

ただ注意点として、Azure Functions の永続ストレージ(ローカルストレージ)が、同一ストレージリソースを複数インスタンスで共通して利用する仕様の為、複数インスタンスから単純にログ出力すると、排他制御で問題が発生する点がある。MinimalLock モードで書き込み毎に排他すれば複数インスタンスからの同一ログ書き込み自体は行えるが、今度はログの取りこぼしが結構な割り合いで発生するので、これも個人的にはお勧めできない。

複数インスタンスでも取りこぼしなくログ出力するには、ログファイル名にインスタンスの情報を含めるとかが考えられるが、それはそれでログ内容を検索するのが大変になりそうなので、そこまでするなら AI や DB など排他の心配が不要なリソースを利用した方が良いかもしれない。

まとめ

基本は、Application Insights を使用。Info 系、Error 系など最低限のログ出力であれば、リアルタイムで確認できることもあり、便利。 AI にプラスして、Debug 系など大量に出力される可能性があるログに関しては、単一インスタンスであれば log4net によるログファイル出力が簡単。 複数インスタンスで実行される可能性がある場合は、単純な log4net ログファイル出力だと排他の問題が発生する為、AI や DB など排他の心配が不要なリソースの利用を検討する。

Azure App Service のレイヤー構成について

レイヤー構成図

f:id:poke_dev:20181030001230p:plain

赤枠は同一 App Service で 2 インスタンス使用している時の例

各レイヤーに関連する項目

  • スロット
    • Azure ストレージ上の永続ストレージ (= デプロイしたアプリ) (d:\home) (スワップ対象) (*2)
    • アプリ設定 (スワップ対象。スロット固定可)
    • IP 制限 (スワップ対象)
    • カスタムドメイン (スロット固定)
    • IIS ワーカープロセス (再起動とかもこの単位)
  • Apps
    • Web Apps、Functions などのアプリ
  • App Service (インスタンス毎)
    • VM インスタンスはこの単位 (スケールアップ、スケールアウトもこの単位) (*3)
    • 課金もこの単位 (動作しているインスタンス分発生)
    • プラン毎の利用可能メモリなどもこの単位
    • 各スロット毎に用意された VM インスタンス上の一時ストレージ (d:\local)
  • App Service (全インスタンス共通)
    • 各スロット毎に用意された Azure ストレージ上の永続ストレージ (d:\home) (*4)
    • SSL 証明書アップロード
  • スタンプ
    • 受信 IP (1 つ)、送信 IP (4 つ)
    • App Service Environment はこのスタンプ毎占有する
(*1) Functions は今のところデプロイ スロットは正式サポートしていない。ここでは常に既定スロットが使用される想定。
(*2, 4) 同じ項目の注釈をスロットと App Service の両方に記載しているので分かりづらいが、永続ストレージはスロット毎に固有の領域が Azure ストレージ上に用意され、全 App Service インスタンスから共有される方式をとる。App Service とは別の Azure リソースを使用しているためここのレイヤー説明に記載するのは微妙だが、App Service が自動で作成して使用する仕様のため、考慮が必要な項目として記載した。
(*3) スタンプ上に配置される App Service インスタンスは、他のテナントの App Service インスタンスも含まれる事に注意。スタンプを共有するインスタンスは、IP も共有する。

その他考慮事項

  • App Service インスタンスは、スケールアウト時も同一スタンプ上にインスタンスが作成される (= 同じ App Service プランのインスタンスであれば、使用する IP は同じ)
  • App Service のプランを変更しない限り、基本的には最初に配置されたスタンプが使用され続ける (= IP は変わらない)。但し、Azure の大規模メンテナンス等が発生した場合、配置されるスタンプが変わる事があり、その場合は結果的に IP も変わる (= 基本的に固定されるが、固定は保証されていない)
  • スケールアウトを考慮しない場合は、単純に一つの App Service インスタンスに複数スロット、複数 Web Apps を詰め込めるだけ詰め込んでも良いが、スケールアウトを考慮する場合、当該 App Service 状に積んでいる Web Apps、スロットがその状態のままスケールアウトする事になるので、注意
  • (参考情報) Functions の従量課金プランは App Service プランとは異なり、関数実行時に都度デプロイされるが、デプロイ先の VM インスタンスが常に同一スタンプ上のインスタンスとは限らない。前回と異なるスタンプ上のインスタンスにデプロイされた場合、IP も変わってしまう (= IP は固定できない)。

参考ドキュメント