Azure Service Fabric 初めての開発 その2

ネクストスケープの照山です。もう少し早めに書く予定でしたが、結局当日に書くことになってしまいました。

前回はService Fabricによる開発を始めるための基礎知識と、ローカルの開発環境で動かすところまでの学習ステップを紹介しました。
今回はそれをAzure上で動かすまでの流れをみていきたいと思います。

#Azure上にService Fabricクラスターを作成
早速、以下のページを参考にAzure上にService Fabricクラスターを作成していきます。
[Azure ポータルを使用して Azure で Service Fabric クラスターを作成する](https://docs.microsoft.com/ja-jp/azure/service-fabric/service-fabric-cluster-creation-via-portal)

Azureポータル上で作成するだけと思いきや、その前にKey Vaultやらクラスター証明書、サーバー証明書とやらが出てきて、PowerShellからの操作が必要になります。

これらが何者であるか簡単に説明します。

・クラスター証明書：Service Fabric上のクラスターに各ノードが認証して通信できるようにするための証明書で、プライマリ証明書とセカンダリ証明書があります。セカンダリはプライマリの期限切れ等で切り替える際に使用すると思われます。
・サーバー証明書：クラスタの管理操作を行うための証明書です。ポータル上では「管理クライアント」と書かれています。これがないとアプリケーションのデプロイやService Fabric Explorerへのアクセスを行うことができません。

ここは結構つまづいたポイントですので、実際のPowerSellのスクリプトを紹介しておきます。
ここではクラスター証明書もサーバー証明書も同じ証明書を使用する前提で進めます。

最初にX.509の自己署名証明書を作成します。

「開発者コマンドプロンプト for VS2015」を管理者で起動し、以下を実行します。
```
makecert -sky exchange -r -n "CN=ServiceFabricCert" -pe -a sha1 -len 2048 -ss My "c:\ServiceFabricCert.cer"
```

CN(証明書名)とファイル名は適当に。
これで有効期限が2040年の自己署名証明書が生成されます。

インポートして、certmgrでエクスポートして、.pfxを作成してください。

次に、PowerShellを使って、証明書(.pfx)をAzure KeyVaultに登録します。

```
$keyfilepath = Read-Host "キーファイルパスを入力してください。";
$subscriptionid = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
$resourcegroupname = 'ResourceGroupName';
$pfxpassword = 'Passowrd';
$keyvaultname = 'KeyVaultName';
$keyname = 'KeyName';
$Location = 'Japan East';

# サインイン
Login-AzureRmAccount;

# サブスクリプションの選択
Set-AzureRmContext -SubscriptionId $subscriptionid;

# リソースグループの作成
New-AzureRmResourceGroup -Name $resourcegroupname -Location $Location;

# KeyVaultの作成
New-AzureRmKeyVault -VaultName $keyvaultname -ResourceGroupName $resourcegroupname -Location $Location;

# Secretの設定
$fileContentBytes = Get-Content $keyfilepath -Encoding Byte;
$fileContentEncoded = [System.Convert]::ToBase64String($fileContentBytes);
$jsonObject = @"
{
"data": "$filecontentencoded",
"dataType" :"pfx",
"password": "$pfxpassword"
}
"@;

$jsonObjectBytes = [System.Text.Encoding]::UTF8.GetBytes($jsonObject);
$jsonEncoded = [System.Convert]::ToBase64String($jsonObjectBytes);
$secret = ConvertTo-SecureString -String $jsonEncoded -AsPlainText -Force;
Set-AzureKeyVaultSecret -VaultName $keyvaultname -Name $keyname -SecretValue $secret;

# Deployの有効化
Set-AzureRmKeyVaultAccessPolicy -VaultName $keyvaultname -EnabledForDeployment;

# 結果の出力
$keyvault = Get-AzureRmKeyVault -VaultName $keyvaultname;
$keyvaultsecret = Get-AzureKeyVaultSecret -VaultName $keyvaultname -Name $keyname;

$certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $keyfilepath, $pfxpassword

Write-Host "SourceKeyVault: " $keyvault.ResourceId;
Write-host "CertificateUrl: " $keyvaultsecret.Id;
Write-Host "CertificateThumbprint: " $certificate.Thumbprint;
```

冒頭の変数は適当な値を設定してください。

ここでは、KeyVaultを作成して、証明書をSecretという形で登録するのが主な作業です。
ファイルをいろいろコンバートして登録しなければいけないのですが、私は正解が分からずにかなりハマりました。
とりあえず、深く考えずにやってみましょう。
リソースグループは、Service Fabricとは別に用意すると管理しやすいと思います。

KeyVaultにSecretを登録できるユーザーは、**対象サブスクリプションに属する「組織ユーザー」**である必要があります。

サブスクリプションの管理者であっても、個人のマイクロソフトアカウントでは上手くいきませんでした。
ポータル上からAzure ActiveDirectoryで組織ユーザーアカウントを作成し、PowerShellでは作成したユーザーでログインして操作を行いましょう。

最後はSourceKeyVaultと証明書URLとサムプリントを出力しています。
これは、Azureポータルで入力する際に必要になるため、コピーしておいてください。

実はここが前半の山場でした。
この後は先に紹介したページに従い、Azureポータル上でクラスタの作成を進めていくことができます。

重要な点としては、ノードタイプという概念を理解することです。
ノードタイプは、Service Fabricクラスタに含まれる仮想マシンのセットを表します。
例えば、WebAPIなどのフロントエンドサービスをホストするVMで構成するノードタイプと、複数のバックエンドサービスをホストするノードタイプを異なるVMサイズと数で構成することができます。
また、ノードタイプ毎にHTTPなどの外部エンドポイントを構成することができます。

![image](https://qiita-image-store.s3.amazonaws.com/0/147012/66823ce6-e601-ce9b-b468-3cf4c0d6b7cf.png)

次にセキュリティの構成をおこないます。
「ソースKey Vault」、「証明書URL」、「証明書の拇印」には、先程コピーしておいた値を入力します。

![image1.png](https://qiita-image-store.s3.amazonaws.com/0/147012/ea891122-19c9-f956-2d14-91ab2f933d75.png)

詳細設定の構成を開くと「セカンダリ証明書」と「管理用クライアント」、「読み取り専用クライアント」の設定が現れるので、管理用クライアントの承認方法に「証明書の拇印」を選択し、プライマリ証明書と同じサムプリントを入力します。

これでクラスタの作成が完了しますが、最後のステップで**リソースマネージャのテンプレートが取得できるので、必ず取得**しておきましょう。作成後に取得することはできないので、注意してください。
診断ログ出力の設定や、ネットワーク設定などを変更する際に必要になります。

クラスターの作成には20～30分くらい掛かるので、気長に待ちましょう。

上手くいかない場合は、アクティビティログなどをチェックして、失敗したポイントを確認し、手順を見直してください。指定したリソースグループには、Service Fabricクラスターに関する多数のリソースが生成されていますが、途中で失敗した場合には、リソースグループごと削除して、最初からやり直しましょう。

#アプリケーションをService Fabricクラスターにデプロイ
Azure上のService Fabricクラスターが作成できたら、アプリケーションをデプロイしてみましょう。
通常、開発段階ではVisual Studioからデプロイすると思います。

以下のページの手順に従って、アプリケーションを発行します。

[Visual Studio を使用してリモート クラスターにアプリケーションを発行する](https://docs.microsoft.com/ja-jp/azure/service-fabric/service-fabric-publish-app-remote-cluster)

「Service Fabric アプリケーションの発行」ダイアログで、デプロイに関する設定を行います。
「接続のエンドポイント」には、Service Fabricの「クライアントの接続エンドポイント」を入力します。Azureポータルから作成したService Fabricクラスターの「概要」で確認することができます。必ずポート番号まで設定してください。
「詳細な接続パラメータ」には、デプロイを行うためのサーバ証明書に関する情報を設定します。

ターゲットプロファイルを一度保存して、XMLを直接編集した方が早いので、そちらの手順を紹介します。
Service Fabricのプロジェクトには「PublishProfiles」というディレクトリがあり、その中に発行プロファイルが保存されます。保存したファイルを開いて、以下のように変更します。
接続エンドポイントと証明書の拇印は適切な値を設定してください。

```
<?xml version="1.0" encoding="utf-8"?>
<PublishProfile xmlns="http://schemas.microsoft.com/2015/05/fabrictools">
  <ClusterConnectionParameters ConnectionEndpoint="XXXXXXXXXX.japaneast.cloudapp.azure.com:19000" X509Credential="true" ServerCertThumbprint="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" FindType="FindByThumbprint" FindValue="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" StoreLocation="CurrentUser" StoreName="My"/>
  <ApplicationParameterFile Path="..\ApplicationParameters\Development.xml" />
  <UpgradeDeployment Mode="Monitored" Enabled="true">
    <Parameters FailureAction="Rollback" Force="True" />
  </UpgradeDeployment>
</PublishProfile>
```

もう一度、「Service Fabric アプリケーションの発行」ダイアログを開いて「発行」をクリックすると、アプリケーションの発行が行われます。

アプリケーションが正常にデプロイされたかどうかは、Visual Studioのログにも表示されますが、デプロイ後のアプリケーション全体の状態や各サービスの状態を確認するには、Service Fabric Explorerから確認してください。
Service Fabric Explorerには、Azureポータル上のService Fabricクラスターの「概要」からアクセスすることができます。アクセスするにはサーバ証明書がローカルマシンにインストールされている必要があります。

私の環境では、なぜかChromeブラウザでは調子が悪いことが多いため、Edgeブラウザからアクセスするようにしています。ローカルクラスターについては、Chromeでも問題なく表示できています。

ここまでで、Azure上にService Fabricクラスターを作成し、そこにアプリケーションをデプロイできるようになりました。

次回は、実際のアプリケーションで必要となるログの構成、環境毎のパラメータ設定、WebサービスへのSSL証明書の適用など、具体的な内容を順次まとめていきたいと思います。