製品に新しいリリースをインストールするとき、私たちは少し緊張しています。 このプロセスを促進し、少し緊張を和らげるさまざまなテクノロジーがあります。 UNIXエンジニアが長年選択してきたこれらのテクノロジーの1つは、 シンボリックリンクの使用です。これにより、リリースの時間を最小限に抑え、「何かがうまくいかなかった」場合に前のリリースにロールバックします(c)。 このメカニズムはWindowsにも存在しますが、何らかの理由で積極的に使用されていません。 しかし、無駄に。 この記事は、この誤解を修正し、リリースを展開するプロセスをより楽しくすることを目的としています。

映画「紳士のフォーチュン」のフレーム
一般に、このテクノロジはASP.NETアプリケーションだけでなく、あらゆる展開(Windowsサービスなど)にも適用できます。 ここでは、IISに展開されたASP.NETが例として使用されています。これは、このアイデアが生まれる前に踏まなければならないいくつかのレーキがあるためです。 他のアプリケーションではよりシンプルになります。
まず、問題が実際に何であるかを説明しましょう。 通常、IIS上のWebアプリケーションファイルは
c:\inetpub\wwwroot\{appName}
あり、デプロイするたびに(たとえばmsdeployを使用して)、古いファイルを新しいファイルで再削除します。 これは、リリース間で変更されず、内容のみが変更される一連のファイルがあるまでは、うまく機能します。 たとえば、次のリリースでライブラリの1つが(名前が異なる)別のライブラリに置き換えられた場合、展開中に新しいライブラリが表示され、古いライブラリは削除されません。 繰り返しますが、突然何かがうまくいかず、以前のリリースにすばやくロールバックしたい場合、新しいリリースからのファイルは消去されないため、別の失敗が待っている場合があります。 シンボリックリンクはこの問題をエレガントに解決します。
特定の例を説明します。 C:ドライブにリリースフォルダーを作成し、アプリケーションのリリースをそのフォルダーに追加します。
C:\Releases\1.1\WebApp C:\Releases\1.2\WebApp
そして、フォルダー
c:\inetpub\wwwroot\
シンボリックリンクWebAppを作成します。フォルダー
c:\Releases\1.1\WebApp
を見て、いつでも
c:\Releases\1.2\WebApp
切り替えることができます。
アプリケーションがいくつかのパラメーターを満たしている必要があることをすぐに警告する価値があります( 12の要因で完全に説明されています)
- リリースフォルダーには、アプリケーションが完全に機能するように、必要なすべてのライブラリとファイルのセットが含まれている必要があります。 暗黙的なリンクはありません。
- リリースは、外部リソース(データベースなど)と互換性がある必要があります。 つまり データベースに変更を加えた場合、アプリケーションは新しいリリースと古いリリースの両方で機能し続ける必要があります。
したがって、Windowsでシンボリックリンクを作成するには、mklinkコマンドを使用します。 この例では、/ Dスイッチを使用しています。これは、これがディレクトリへのリンクであることを意味します。
mklink /D c:\inetpub\wwwroot\WebApp c:\Releases\1.1\WebApp
実際にはすべて。 特別なアイコンが付いたWebAppディレクトリがwwwrootフォルダーに表示されていることを確認できます。これをダブルクリックすると、リリースフォルダー1.1が表示されます。 IISのこのフォルダを右クリックして適切なアイテムを選択することにより、Webアプリケーションに変換することは残ります。 ブラウザに移動して、すべてが機能することを確認します。
リリースの「切り替え」には、いくつかの困難があります。 実際、ASP.NETアプリケーションはコンパイルされ、最初の起動時にキャッシュに書き込まれます。 将来、IISはweb.configファイルの変更を確認し、変更が発生した場合、アプリケーションを「再構築」します。 シンボリックリンクの場合、IISはこれらの変更を認識しないため、シンボリックリンクを新しいディレクトリに切り替えただけでは何も起こりませんが、古いリリースは機能します。 すべてが機能するためには、キャッシュをクリアする必要があります。 Googleはiisresetコマンドでこれを行うことをお勧めします。これによりW3SVCサービスが再起動されますが、これは私たちにとって過激すぎるためです。このサーバー上の他のアプリケーションを再起動したくないのです。 幸いなことに、IISでは、サービス全体ではなく、サイト自体またはそのプールのみを再起動できます。 すぐに言わなければならない-何らかの理由でサイトを再起動することは非常に不安定であることが実験的に確立された。 その後、彼はアプリケーションを再構築しますが、そうではありません。その後、一般的には未知のラスコリャークで立ち上がります。 しかし、プールの再起動は非常にうまくいきます。
そしてもう一つのニュアンス。 mklinkコマンドでは、リンクを「切り替える」ことはできません。 したがって、最初にrmdirコマンドで削除してから、別のパスで再作成する必要があります。 そのため、リンクを切り替えるには、次の手順を実行する必要があります。
- プールを止める
- シンボリックリンクを削除します。
- 新しいパスでリンクを作成します。
- プールを実行します。
C:\> C:\Windows\System32\inetsrv\appcmd stop apppool DefaultAppPool C:\> rmdir c:\inetpub\wwwroot\WebApp C:\> mklink /D c:\inetpub\wwwroot\WebApp c:\Releases\1.2\WebApp C:\> C:\Windows\System32\inetsrv\appcmd start apppool DefaultAppPool
このアプローチは、別のおいしいパンを提供します。 たとえば、IISでは、ポート8080などで別のサイトを上げることができます。次に、新しいリリースでそのサイトのシンボリックリンクを作成します。 したがって、古いリリースは80、新しいリリースは8080になります。リラックスした雰囲気の中で新しいリリースを確認し、メインサイト(ポート80にある)を新しいフォルダーに切り替えることができます。
結論として、このプロセスを自動化するPowerShellスクリプトを提供したいと思います。
スクリプトテキスト
param([string]$Release=$null,[string]$AppName=$null,[string]$AppPath="C:\inetpub\wwwroot\",[string]$ReleasesPath="C:\Releases\",[string]$PoolName="DefaultAppPool"); if ($Release) { if($AppName) { Write-Output "!"; Write-Output " ..."; cmd /c "C:\Windows\System32\inetsrv\appcmd stop apppool $PoolName"; Write-Output " $AppName."; $link = $AppPath+$AppName; Write-Output "Link: $link"; $target=$ReleasesPath+$Release+"\"+$AppName; Write-Output "Target: $target"; if(Test-Path $target) { # , if (Test-Path $link) { cmd /c "rmdir $link" Write-Output " $link"; }; # cmd /c "mklink /D $link $target" } else { Write-Error " : $traget"; } Write-Output " ..." cmd /c "C:\Windows\System32\inetsrv\appcmd start apppool $PoolName"; Write-Output "Ok!" } else { Write-Error " AppName"; } } else { Write-Error " Release!" }
そこには次のパラメーターが渡されます。
- リリース-リリースのあるフォルダーの名前。
- AppName-アプリケーションの名前。
- AppPath-アプリケーションへのパス(シンボリックリンクがある場所);
- ReleasesPath-リリースがある方法。
- PoolNameはプールの名前です。
その他...
PowerShell 5.0は、 シンボリックリンクをサポートするようになりました。 したがって、5番目のバージョンとIIS powershell制御モジュール(
PS> Import-Module WebAdministration
)をインストールすると、純粋なpowershellですべてを実行することにより、cmdコマンドをまったく使用せずに実行できます。
Powershell 5.0スクリプトテキスト
param([string]$Release=$null,[string]$AppName=$null,[string]$AppPath="C:\inetpub\wwwroot\",[string]$ReleasesPath="C:\Releases\",[string]$PoolName="DefaultAppPool"); if ($Release) { if($AppName) { Write-Output "!"; Write-Output " $PoolName..."; Stop-WebAppPool $PoolName -Passthru; Write-Output " $AppName."; $link = $AppPath+$AppName; Write-Output "Link: $link"; $target=$ReleasesPath+$Release+"\"+$AppName; Write-Output "Target: $target"; if(Test-Path $target) { # New-Item -ItemType SymbolicLink -Path $AppPath -Name $AppName -Value $target -Force } else { Write-Error " : $traget"; } Write-Output " ..." Start-Sleep 3; # :) Start-WebAppPool $PoolName -Passthru; Write-Output "Ok!" } else { Write-Error " AppName"; } } else { Write-Error " Release!" }