しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

Windows Server Version 1709 から Windows Server Containers のバージョン要件が変更されていた

これまで何回か Windows Containers を触ってきましたが、大体は Windows Server Containers の場合はバージョンを合わせるのが面倒なので、Hyper-V Containers を使おうという方向に落ち着いてました。

ビルド番号が異なる場合には起動がブロックされますが、リビジョン違いは起動はするものの本番環境でサポートは行わないという鬼のような要件です。

なので、使うには Hyper-V Containers を使って完全に分離してあげないと、と思ってました。

最近、何となくドキュメントを眺めていたら Windows Server Version 1709 からはバージョン周りの要件が変更されていて、リビジョンは一致していなくても本番環境でサポートされるようになったみたいです。

正直なところカーネルを共有してるので、この制限は撤廃されないだろうなと考えてました。

ドキュメントによると 1709 からはコンテナホストとリビジョンまで合わせる必要はないが、最新のアップデートを適用しておくのをお勧めしますということのようです。

For Windows Server 2016 based hosts/images – the container image’s revision must match the host to be in a supported configuration. Starting with Windows Server version 1709, this is no longer applicable, and the host and container image need not have matching revisions. It is as always recommended to keep your systems up-to-date with the latest patches and updates.

Windows Container Version Compatibility | Microsoft Docs

LTSC での運用はほぼ不可能じゃないかと思ってましたが、アップデートを重ねることで何だかんだで実用的になってきているなと感じました。

運用ではコンテナホストのアップデートを考える必要がありますが、上のドキュメントには Kubernetes の nodeSelector を使って一致するバージョン上で Pod を実行させるための方法も載っています。しかし、肝心のノードを追加する方法が今の AKS には用意されていないので、単純にクラスタを作ると詰みます。

一応は対応予定ではあるらしいので、追加できるようになると新しい Windows Server のビルドをノードとして追加して、nodeSelector を使って切り替えるだけでアップデートが完了するわけです。

CI 周りも VSTS / AppVeyor / CodeBuild 以外にも、Codefresh という Kubernetes 向けサービスが Windows Containers にベータですが対応を始めているので、去年から割と整ってきた感じがあります。

Codefresh は結構面白そうなので、Windows Containers のサポートを試して見ようかと思います。

AWS CodeBuild が Windows に対応したらしいので試した

Twitter を眺めていたら AWS CodeBuild が一部のリージョンで Windows に対応したとあったので、早速オレゴンで試して見ることにしました。

Windows が使えるビルドサービスは VSTS か AppVeyor ぐらいしか選択肢がなかったので貴重です。

AWS CodeBuild Adds Support for Windows Builds

Microsoft Windows Samples for AWS CodeBuild - AWS CodeBuild

buildspec.yml は特に Windows だから変わっている部分はないみたいです。新しいビルドプロジェクトを作成する時に OS や利用するランタイムを選べるようになっています。

AWS 管理のイメージも用意されていますが、Docker Hub で公開されている任意のイメージも利用できるようになっているみたいです。これは地味に良さそう。

f:id:shiba-yan:20180527152305p:plain

ビルドした結果は S3 に保存できるので、結構扱いやすいです。実際に ASP.NET アプリケーションをビルドして、WebDeploy パッケージを作成してみましたが、すんなりと S3 に保存されてました。

f:id:shiba-yan:20180527204658p:plain

試した感じでは、まだコンテナを利用した Windows アプリのビルド環境が未成熟という印象を持ちましたが、AppVeyor の地位危うしという感じがします。

やはり毎回 init で必要なパッケージをインストールしたりするのは時間の無駄ですからね。

f:id:shiba-yan:20180527210045p:plain

CodeBuild の場合は利用するコンピューティングタイプを選択できるのも良いです。Windows Containers 自体が重いのもありますが、選択肢があるというのは重要です。

CodeBuild 提供の Windows イメージ

CodeBuild で提供されているイメージは msbuild へのパスが通っていないので、そのままだとビルドが通らないので地味に厄介です。フルパスで msbuild を指定しないとエラーになります。

f:id:shiba-yan:20180527152338p:plain

ライセンス情報を見る感じでは .NET 4.6.2 までしか Targeting Pack が入っていないみたいなので、4.7 以降をターゲットにしたアプリケーションはビルド出来ないかも知れません。

AWS CodeBuild for Windows—Third Party Notices - AWS CodeBuild

.NET Core についても、パッと見た感じでは 2.0 しか SDK が入っていないように見えます。

それ以外のバージョンをビルドする場合には専用の Docker Image を用意するか、Microsoft から公式リリースされているものを使った方が良さそうです。

.NET Command Line Tools (2.1.103)

Product Information:
 Version:            2.1.103
 Commit SHA-1 hash:  60218cecb5

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.14393
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\2.1.103\

Microsoft .NET Core Shared Framework Host
  Version  : 2.0.6
  Build    : 74b1c703813c8910df5b96f304b0f2b78cdf194d

.NET Core の場合は Nano Server ベースのイメージを使えるのでプロビジョニングの短縮が図れます。

カスタムイメージを作成する

Microsoft から提供されているイメージは何故か WebBuildTools がインストールされていないので、ASP.NET アプリケーションのビルドには微妙に問題が出ます。

予めパッケージをインストールしておきたいという要望もあるはずなので、AWS Blog に書いてあるようにカスタムなイメージを作成して対応しましょう。

Extending AWS CodeBuild with Custom Build Environments for the .NET Framework | AWS DevOps Blog

こっちはちゃんと WebBuildTools をインストールするコマンドになっているので、ASP.NET アプリケーションのビルドも問題ありません。

pull されたイメージはキャッシュされる

条件はよくわかっていませんが、同じイメージを使っている場合にはキャッシュが効いて素早くビルドまで実行できるようになっていました。

単純に同じホストに割り当てられた場合のみなんでしょうが、Server Core のイメージは重いので重要です。

f:id:shiba-yan:20180527160521p:plain

欲を言えば、予めよく使われそうなイメージは pull 済みになっておいて欲しいですね。

LTSC 2016 のみ実行可能

.NET Framework SDK の Docker Image は LTSC 2016 以外に 1709 / 1803 が提供されているので、そのイメージを利用してビルドを実行してみましたが、コンテナが立ち上がることなく失敗しました。

f:id:shiba-yan:20180527155527p:plain

なので Hyper-V Containers ではなくて Windows Server Containers を利用していることが分かります。

軽量化された Docker Image は CodeBuild では暫く使えそうにないですね。残念ながら Windows Server 2019 のリリースを待つしかなさそうです。

ConoHa が Windows Server に対応したので契約してみた

前から Linux の VPS は主に Docker 用として契約して使ってましたが、Windows Server にも対応したと聞いたので早速契約してみることにしました。

10% オフになっても 2GB プランはまあまあのお値段という感じがします。

どうやら Windows Server 2016 Datacenter だけのイメージと SQL Server が入ったイメージが選べるようになっているみたいです。SQL Server 入りを選ぶとライセンス分が上乗せされるので高くなります。

ConoHa の Windows Server は珍しく 3 コアのマシンが選べます。

f:id:shiba-yan:20180425002440p:plain

人生で 3 コアのマシンを使ったことがなかったので、試してみることにしました。

リモートデスクトップ用のパスワードを入力して、追加ボタンを押せば VM が作成されます。プロビジョニングは結構早いです。そしてブラウザからデスクトップが確認出来るのはかなり良いですね。

f:id:shiba-yan:20180425002953p:plain

最初は「どうせ Windows Server では動作しないんだろ」とか思ってました。ごめんなさい。

デフォルトの Windows Server 2016 のバージョンは少し古いものでした。デフォルトで日本語 OS が起動するのが、地味に便利な気がしますね。

f:id:shiba-yan:20180425003236p:plain

この状態で Windows Update を実行すると、累積アップデートが落ちてきます。Azure や AWS は少し遅れて新しいイメージが提供されてますが、ConoHa ではどうなるのか気になります。

そしてタスクマネージャーの表示です。3 コアだと微妙に収まりが悪いですね。

f:id:shiba-yan:20180425003017p:plain

当然ですが、Windows Server 2016 の VM を作成しても、そのままでは何も出来ません。最低限 Web サーバーとして運用するためには IIS を入れる必要があります。

ConoHa のデフォルトではファイアウォールが全ポート許可になっているので、実際に使う際にはちゃんと必要なポートだけ開けるようにして使ってください。

Web Deploy を使ってデプロイ

IIS を入れてもアプリケーションのデプロイは必要になるので、Web Deploy をインストールして Visual Studio や MSDeploy を使ってリモートでデプロイ出来るようにしないと、使い道が無さそうです。

Web Deploy のインストールは癖があるので、いい感じに記事を参考にしてください。

適当に Web Deploy をインストールして、発行用のユーザーを作成し、publishsettings ファイルを作成して Visual Studio にインポートします。この辺りは App Service を使っている場合と同じです。

f:id:shiba-yan:20180425015521p:plain

証明書周りの警告が出ますが、オレオレ証明書なのでスルーします。

デプロイが完了すると、見慣れた ASP.NET アプリケーションが表示されました。問題なく動いてますね。

f:id:shiba-yan:20180425015602p:plain

MSDeploy を使ってデプロイが出来るので、AppVeyor や VSTS から簡単に扱えるはずです。

Docker を使う

ちなみに ConoHa でも Docker EE をインストールして Windows Server Containers を使うことが出来ます。Nested Virtualization には対応していないので Hyper-V Containers は無理です。 ごめんなさい、Hyper-V Containers 使えました。

インストールは Docker 公式のドキュメントを読んでください。このブログでも何回か書きました。

Server Core のイメージはサイズが大きすぎるので Nano Server を pull してきました。

動作確認を簡単にするために、IIS がインストールされたものを使います。8080 を 80 にフォワーディングするように指定して、Nano Server なコンテナーを起動します。

f:id:shiba-yan:20180425013110p:plain

コンテナーホストの外から 8080 にアクセスすると IIS のスタートページが表示されます。

f:id:shiba-yan:20180425013328p:plain

簡単な Windows Server Containers の検証としても良い感じですね。メモリが 2GB では心許ないですが、お遊びでは十分という感じもします。

最後に気が付いたのですが、何故か起動した Windows Server は時計が 1 時間遅れていました。タイムゾーンは合ってたので、NTP を使うと日本時間に戻りましたが謎です。

追記 : Hyper-V Containers も使えました

書いたときは Hyper-V を微妙に見落としていたのか、Install-WindowsFeature Hyper-V であっさりとインストールした後に、docker run で isolation を hyperv にすると Hyper-V Containers として起動できました。

タスクマネージャーを見ると wmwp や vmmem が動いてることが確認できます。

f:id:shiba-yan:20180425105806p:plain

大きめのインスタンスを契約すれば Azure Functions Runtime などのインストールも出来そうな気がします。

Windows Server Insider Preview Build 17079 で Server Core Container のサイズが更に削減

Windows Containers を使って ASP.NET アプリケーションの Dockernize を行う上で最大の問題となる、Server Core な Docker Image のサイズが 17079 で更に削減されました。

ブログでは 30% 削減されたと書いてありますが、実際のサイズはダウンロード時が 1.58GB で展開後のディスク上では 3.61GB にまで小さくなったらしいです。

初期の Docker Image は展開後 10GB あったことを考えると 1/3 近くになってます。

他にも MSMQ がプリインストールされたとか、アプリケーションの互換性が向上したとありますが、具体的にどう変わったかは公開されてないので分からないです。

Virtualization のブログではもっと詳細な内容が公開されているので面白いです。

今回のイメージサイズ削減は Nano Server と同じ方法を使って削減したとか、利用者から送信されるテレメトリーから使われていない機能を削除したとか、非常に興味深い話です。テレメトリーを使っているので、今後も使っていくほどにサイズが小さくなっていく可能性がありますね。*1

まだ WOW64 が残っているらしいので、今後削除が行われると更に小さくなる可能性がありそうです。

今回のビルドでは In-place Upgrade がやっと行えるようになったらしいですが、例によって Semi-Annual な Windows Server は Server Core しか提供されておらず使いにくいので、検証には Windows 10 Insider Preview を使いました。

カーネルのバージョンが異なっていますが、Hyper-V Containers なら問題なく扱えるようになってます。とりあえずメジャーな Docker Image を pull してきてサイズを比較してみました。

f:id:shiba-yan:20180126010551p:plain

windowsservercore-insider と windowsservercore:1709 の差が大きいですね。Nano Server も小さくなっているように見えますが、Windows Update でレイヤーが増えた結果かもしれないので確証はありません。

Server とは関係ないですが、最新の Windows 10 Insider Preview Build 17083 でもループバックアドレスで、実行中のコンテナにアクセス出来るようになっていました。これはやっぱり地味に嬉しい。

Insider Preview な Server Core には IIS が入ったものがないので 1709 で試してますが、問題なく localhost でアクセスが出来ています。RS4 からは inspect する必要が無くなります。

f:id:shiba-yan:20180126010505p:plain

慣例的に Insider Preview な Server Core 向けには ASP.NET 向けのイメージも公開されないので、試して見たい場合には公開されている Dockerfile を使って自前でビルドする形になります。

ちなみに ASP.NET 4.7 のイメージを作ってもサイズは結構小さいままでした。

f:id:shiba-yan:20180127134435p:plain

とりあえず ASP.NET MVC 5 アプリケーションを動かすイメージをビルドして実行してみました。当然ですが、何の問題もなく普通に動きます。

f:id:shiba-yan:20180127141423p:plain

Server Core のサイズが小さくならないと ASP.NET アプリケーションの Dockernize は現実的ではないスタンスでいましたが、現実的なサイズになってきたので嬉しいですね。後は CI SaaS で使えるようになれば準備が整いそうです。

RS4 でやっと Windows Containers が現実的な時間で扱えるようになりそうです。

*1:ちなみに削除された機能の一覧はこれ https://gist.github.com/weijuans/19a04903a24487c296effa3f88b603e6

Windows Server Insider Preview Build 17035 で Windows Containers 周りが改善

ちょっと前に次の Semi-Annual Channel 向けの Windows Server Inside Preview がリリースされてました。ぶちぞう RD が空リプしてましたが、6 時とか完全に寝てるので気が付きません。

S2D とか個人的にはどうでもよくて、やっぱり注目はずっと WinNAT 周りの制約と言い続けてきた、ループバックアドレスでコンテナにアクセスできない点が解消されたことです。

  • Developers can now use localhost or loopback (127.0.0.1) to access services running in containers on the host
Announcing Windows Server Insider Preview Build 17035 - Windows Experience BlogWindows Experience Blog

Windows Containers では docker run 時に指定したポートフォワーディングの指定が実質的には動作しておらず、docker inspect を叩いてコンテナの IP アドレスを取得して、直接見に行くことしか出来ませんでした。

それが次の Semi-Annual Channel では解消されて、他のプラットフォーム上の Docker と同じように、簡単にループバックアドレスを使ってアクセス出来るようになります。多分 Windows 10 でも同じでしょう。

ちゃんと Azure 上に Nested VM を作成して、ループバックアドレスで見れるか確認しました。

f:id:shiba-yan:20171119182628p:plain

見ての通り、問題なくループバックアドレスでポートフォワーディングが動いてることが分かりました。

Visual Studio の Docker 拡張は docker inspect を内部的に叩いているので、将来的にはループバックアドレスを使うように挙動が変更されるかも知れません。

そしてブログには書いていませんでしたが、Insider Preview の Docker Image をダウンロードしてくると、Version 1709 と比べて Server Core は 1GB ほどサイズが削減されていました。

f:id:shiba-yan:20171119182413p:plain

Insider Preview の段階では IIS / ASP.NET / .NET Framework などの Insider 向けイメージが提供されていないので、今回は IIS だけ GitHub から Dockerfile などを落としてきて、自分でイメージをビルドしました。

初期の Server Core が展開後 10GB ほどあったことを考えると、半分以下になったことになります。

今の Version 1709 でも初回にかかる時間が半分ぐらいになっていて、割と我慢できるぐらいの時間になってますが、さらに短縮される可能性がありそうです。そろそろプロダクションで使ってみたい。

Windows Server Version 1709 で Docker と Windows Containers を使ってみる

自宅の検証用 Windows Server 2016 を Version 1709 にアップグレードしたので、例によって Docker 周りで気になる部分だけまとめておくことにします。Tech Summit は Version 1709 ベースで話したいですし。

Windows Server Blog や Azure Blog では Azure Marketplace から使えると書いてますが、最近になってようやく Marketplace に 1709 が出てくるようになりました。

f:id:shiba-yan:20171107020751p:plain

例によって Azure の場合は Dv3 / Ev3 を選ぶことで Nested Virtualization を使って Hyper-V Containers が利用可能になります。それにしても対応リージョン増えないですね。

自宅に NUC で作ったマシンがあったので、MSDN から Version 1709 の ISO をダウンロードしてきて、インストールしてみることにしました。気軽にインストールしたら少しはまったので軽くそこから書きます。

ちなみに Linux Containers についてはムッシュが既に書いているので、そっちを参照してください。

流石ムッシュ、SQL Server だけじゃなくて Docker も Linux Container も出来る。

Version 1709 は Server Core / Nano Server のみ

Insider Preview の時は Server Core しか提供されてなかったのは知っていたのですが、GA になればデスクトップ付きもリリースされるだろ、と甘く思って自宅 Windows Server 2016 のアップグレードを行ったところ、Server Core になっていて焦りました。

思わずぶちぞう RD に相談するぐらい焦りました。ちゃんとドキュメント読んでなかったです。

ドキュメントには Semi Annual Channel では Server Core と Nano Server のみとしっかりと書いてあります。そろそろサーバーでデスクトップとか言う現状を、捨てる必要があるのかも知れませんね。

Long-term Servicing は今後どのようにアップデートされていくのかもよくわかりませんが、基本的には Semi Annual Channel に乗っかっていくのが現実的な選択肢なのかと思いました。

特に Windows Containers を使う場合には追従は必須だと思われます。

Docker のインストール

Microsoft のドキュメントだと DockerMsftProvider を使うように書いてますが、微妙にバージョンが古いのが落ちてくるようになってます。この現状に Docker の人がしびれを切らしたのか、fork されて DockerProvider というのが配布されています。

なので Docker 側のドキュメントでは DockerProvider を使うようにと書いてあります。

といっても使い方はほぼ変わらず、DockerMsftProvider から DockerProvider に変えるだけです。

Install-Module DockerProvider -Force
Install-Package Docker -ProviderName DockerProvider -Force

これでインストールが完了しますが、Hyper-V Containers を使う場合には別途 Hyper-V をインストールする必要があります。

Install-WindowsFeature Hyper-V

自分の環境では何故かコンテナからインターネットへの通信が出来ない事象が発生しました。ぶちぞう RD と話しながら解決策を探しましたが、結局わからなかったので Azure に構築しました。

Version 1709 向け Docker Image

Version 1709 では Server Core / Nano Server のイメージサイズが大幅に削減されています。Nano Server は Debian と同じぐらいにまで小さくなってますし、Server Core もまあまあ小さくなりました。

今のところ Docker Hub で公開されている Version 1709 向けイメージは以下の通りです。

# Server Core 1709
docker pull microsoft/windowsservercore:1709
docker pull microsoft/dotnet-framework:4.7.1-windowsservercore-1709
docker pull microsoft/iis:windowsservercore-1709
docker pull microsoft/aspnet:4.7.1-windowsservercore-1709

# Nano Server 1709
docker pull microsoft/nanoserver:1709
docker pull microsoft/aspnetcore:2.0.0-nanoserver-1709

タグ名の付け方は大体見たらわかるような感じですね。

f:id:shiba-yan:20171107021107p:plain

新しい Version 1709 向け Docker Image を使うには当然ながらホストが Version 1709 である必要があるので、今のところは自前で環境を用意する必要があるのが少し辛いところです。

VSTS や AppVeyor も Server Core のみ提供の 1709 に対応してくるかわからないので、下手したら CI サービス全滅という可能性もありそうです。

Windows Server Insider Preview を使って Server Core と Nano Server の Insider Image を試す

あまり Windows Server Insider Preview に関しては興味がなかったのですが、たまたま見つけた Insider 版の Windows Server Core と Nano Server の Docker Image がかなり最適化されていたので、実際に試してみたくなりました。地味にはまりましたが何とか動いたという苦労話です。

手持ちの Hyper-V を入れてある Windows Server 2016 に Insider Preview を入れました。

ダウンロードには Insider Preview への参加が必要ですが、Windows 10 で参加しておけば OK です。

Server Core 版のみ提供されているので、インストールイメージは 2GB ちょいなので小さめですね。

Download Windows Server Insider Preview

最初は Azure 上に作ろうかと思いましたが、ぶちぞう RD から難しそうと言われたので止めました。将来的には Azure で Insider Preview のイメージが提供される気がします。

Windows Server Insider Preview を用意

とりあえず Hyper-V を使って、サクッと Insider Preview をインストールします。コンテナを実行するのでメモリだけは少し多めに確保した方が良い気がしました。

f:id:shiba-yan:20170719221753p:plain

Server Core の初期セットアップ初めてでしたが、基本はパスワード入れるだけです。

f:id:shiba-yan:20170719222207p:plain

Insideer Preview 自体はすぐに入るのですが、その後の Docker インストールで大きく躓きました。すぐに直る気がしますが、ひとまずは回避法を次で紹介しておきます。

Docker をインストール

Docs に Insider Container を使う方法が書いてあるので、基本はこの通りにコマンドを打ち込めばよいはずなのですが、何故か上手くいきませんでした。

Using Insider Container Images | Microsoft Docs

Docker をダウンロードした後のハッシュチェックが通りませんでした。

f:id:shiba-yan:20170719224848p:plain

Provider のコードを読むと、既にファイルがある場合にはダウンロードをスキップするようになっていたので、事前にダウンロードしておきました。パスはユーザーによって異なると思います。

Invoke-WebRequest https://dockermsft.blob.core.windows.net/dockercontainer/docker-17-06-0-ce.zip 
    -OutFile C:\Users\ADMINI~1\AppData\Local\Temp\1\DockerMsftProviderInsider\Docker-17-06-0-ce.zip

この後に再度インストールを実行すると上手くいきました。本当に謎です。

f:id:shiba-yan:20170719225324p:plain

再起動すると dockerd が立ち上がるので、実際にコマンドが使えるようになります。エラーでサービスが立ち上がらなかった時には、もう一度再起動すると上手くいくこともあるみたいです。

Insider Image を試してみる

Docker のインストールに非常に手間と時間をかけてしまいましたが、これでようやく Insider Preview な Image を試すことが出来ます。公開されているベースイメージは以下の通り。

https://hub.docker.com/r/microsoft/windowsservercore-insider/
https://hub.docker.com/r/microsoft/nanoserver-insider/

他にも .NET Core 2.0 や PowerShell が入っているものはあります。

大きな特徴として、イメージサイズが両方とも半分以下になっています。てっきりコンテナに最適化されるのは Nano Server だけかと思ってましたが、Server Core も最適化されました。

f:id:shiba-yan:20170719234055p:plain

これまでの Windows Server Core と Nano Server のサイズは以下の通りです。

f:id:shiba-yan:20170719234357p:plain

展開後のサイズで Nano Server が 200MB を切っているのは割と頑張ったほうだと思います。Server Core はまだまだ大きいですが、それでも .NET Framework の実行環境として扱いやすくなりました。

当然ながら Windows Server Containers ですんなりと動作します。

f:id:shiba-yan:20170719234635p:plain

起動時間の短縮とかはなさそうですが、サイズが小さくなったのは非常に嬉しいです。

Server Core Insider に IIS を入れる

Windows Containers を使ってやりたいことは ASP.NET アプリケーションの Dockernize なので、最低でも IIS を入れて動かしておくことにします。

IIS や ASP.NET の Dockerfile は GitHub に公開されてるので、FROM を買えるだけで使えます。

GitHub からリポジトリを落としてきて、Dockerfile を以下のように書き換えてビルドすると IIS がインストールされた Server Core Insider の Docker Image が完成します。

FROM microsoft/windowsservercore-insider

RUN powershell -Command Add-WindowsFeature Web-Server

ADD ServiceMonitor.exe /ServiceMonitor.exe

EXPOSE 80

ENTRYPOINT ["C:\\ServiceMonitor.exe", "w3svc"]

Dockerfile だけではなく ServiceMonitor が必要なので少し注意が必要です。

ビルドしたイメージを起動すると、当たり前ですが IIS にアクセスできるようになります。特筆すべきことはありませんでしたが、当たり前に動作するというのは重要なポイントかなと。

f:id:shiba-yan:20170719235911p:plain

Windows Containers を運用する上で大変なのは Docker Image のサイズとコンテナホストとのバージョンミスマッチの二つだったので、次のリリースでイメージのサイズに関しては解消されそうです。

コンテナホストとのバージョンミスマッチに関しては Hyper-V Containers が使える Dv3 / Ev3 で半分は解消されたと思ってます。後は Kubernetes 側で isolation を選べるようになれば良いですね。

Docker for Windows Server 2016 のアップデートを行う方法

Windows Server 2016 への Docker インストールは、PowerShell を使って結構簡単に出来るのですが、アップデート方法をこれまであまり見たことがありませんでした。

何回か書いた気はしますが、インストールは以下のコマンドを実行するだけです。

Install-Module -Name DockerMsftProvider -Force
Install-Package -Name docker -ProviderName DockerMsftProvider -Force
Restart-Computer -Force

自宅にある検証マシンに入っている Docker は 1.13 と古いものだったので、簡単にアップデートする方法がないか少し探してみると、PowerShell を使って簡単にアップデート出来るようでした。

ドキュメントの分かりにくい部分にアップデート方法が書いてありました。

Tip: If you want to update Docker later:

  • Check the installed version with Get-Package -Name Docker -ProviderName DockerMsftProvider
  • Find the current version with Find-Package -Name Docker -ProviderName DockerMsftProvider
  • When you're ready, upgrade with Install-Package -Name Docker -ProviderName DockerMsftProvider -Update -Force, followed by Start-Service Docker
Windows Containers on Windows Server | Microsoft Docs

実質、実行するコマンドは以下の 1 行だけです。インストールの時と異なり、Update スイッチが追加になっているだけです。コマンドレット名が分かりにくいですが、これでアップデートも行えるみたいです。

Install-Package -Name docker -ProviderName DockerMsftProvider -Verbose -Update

実際に自宅の検証マシンに対して Docker のアップデートを行ってみました。

Docker 1.13 へのアップデートは半分手動で行った記憶がありますが、関係なく PowerShell でアップデートが出来るようです。これはかなり簡単でした。

f:id:shiba-yan:20170531010031p:plain

アップデートが完了した後は dockerd が立ち上がっていなかったですが、Windows Update のついでに再起動を行ってみると無事に立ち上がってきました。

docker version を実行してみると、ちゃんと最新の 17.03.1-ee-3 になっていることが確認できますね。

f:id:shiba-yan:20170531010246p:plain

Windows Server 2016 では追加コスト無しで EE 版が使えるようになってるので、自然とこのバージョンが落ちてくるようです。手順をすぐに忘れそうなので、メモ代わりに残しておきます。

Kubernetes で .NET アプリケーションな Job を動かしてみる

Kubernetes には Job という機能があることを知ったので、Windows Server Containers でも試してみました。使いどころはわかってないですが、Windows でも動くことを確認したかったのです。

動き続けるタイプの Job を作りたい場合には、これまで通り Deployment と Replica Set を使った方が良さそうです。Job のイメージ定義は immutable なので後から変更できません。

とりあえず適当にコンソールアプリケーションを作成します。標準出力にメッセージを書くだけのアプリケーションをサクッと用意してビルドします。

using System;
using System.Threading;

namespace JobApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello Job : " + DateTime.Now);
        }
    }
}

このアプリケーションをイメージ化するために用意した Dockerfile は以下の通りです。ENTRYPOINT としてビルドしたアプリケーションを指定して、実行が終わったらコンテナも終わるようにします。

FROM では .NET Framework 4.6.2 のイメージを明示的に指定しておきます。ちなみに microsoft/dotnet は .NET Core を使うイメージなので注意。

FROM microsoft/dotnet-framework:4.6.2

COPY app /app

WORKDIR /app

ENTRYPOINT ["JobApplication.exe"]

作成したイメージを Docker Hub に push し、Kubernetes にデプロイするための YAML を用意します。ダッシュボードから作れないので YAML を用意する必要がありました。

最重要ポイントとして nodeSelector で os を windows として明示的に指定しないと、Linux で動作しているマスターにデプロイされて詰みます。

apiVersion: batch/v1
kind: Job
metadata:
  name: dotnet-job
spec:
  template:
    metadata:
      name: dotnet-job
    spec:
      containers:
      - name: dotnet-job
        image: shibayan/dotnet-job
      restartPolicy: OnFailure
      nodeSelector:
        beta.kubernetes.io/os: windows

これに気が付かずに何回も pull 時にエラーを出してしまって悩みました。デプロイメントを作成した時に上手くいった理由はよくわからないですが、Windows Server Containers を使うので指定は必要だと思います。

YAML を作成したら Kubernetes のダッシュボードからアップロードするだけです。

f:id:shiba-yan:20170504162100p:plain

デプロイが完了すると Job が実行されて、ログが見れるようになります。

f:id:shiba-yan:20170504162149p:plain

とりあえず Windows Server Containers でも動作はしましたが、再実行するには Job の再デプロイが必要なので、いまいち使いどころがやっぱりわかりませんでした。

ちょっと前に追加された Cron Jobs の方が使いどころが多いと思いました。

しかし、現在の Azure Container Service で作られた Kubernetes では有効化されていないので、残念ながらデプロイのタイミングで検証エラーになってしまいます。

f:id:shiba-yan:20170504163046p:plain

acs-engine を使えばカスタマイズ出来そうですが、それはまた今度試してみることにします。

nodeSelector について学べたので、今回はそれで良しとしておきます。

AppVeyor から Azure Container Service 上の Kubernetes へ自動でデプロイを行う

これまで AppVeyor と Kubernetes でやってきたことの集大成として、AppVeyor から Azure Container Service 上の Kubernetes への自動デプロイを試してみます。

やってきたことは以下のエントリを参照してください。Kubernetes はかなり良いですね。

AppVeyor から Kubernetes にデプロイするためには、認証情報が必要なので先に作成しておきます。

Service Account Token を取得

トークンを作成するためには kubectl を使って Service Account をまず作成する必要があります。

kubectl create serviceaccount appveyor

コマンドで Service Account を作成したら、ダッシュボードでトークンを確認できるので簡単です。

コンフィグの中にあるシークレットから、Base64 デコード済みのトークンをコピーできます。

f:id:shiba-yan:20170503210641p:plain

作成はコマンドで作りますが、削除と編集はダッシュボードから簡単に行えるのがアンバランスでした。

appveyor.yml に処理を追加

現在の Kubernetes ダッシュボードは以下のようになっています。基本的にアップデートを行うだけなので、予めアプリケーションはデプロイしてあります。

f:id:shiba-yan:20170503211019p:plain

appveyor.yml には kubectl のダウンロードと、イメージの更新コマンドを追加します。

version: '{build}'

image: Visual Studio 2017

environment:
  DOCKER_USER: XXXXX
  DOCKER_PASS:
    secure: XXXXX
  DOCKER_IMAGE_NAME: shibayan/appveyor-aspnet-docker:$(APPVEYOR_REPO_BRANCH)-$(APPVEYOR_BUILD_NUMBER)
  KUBE_MASTER: https://XXXXX
  KUBE_TOKEN:
    secure: XXXXX

install:
  - curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.6.2/bin/windows/amd64/kubectl.exe

before_build:
  - nuget restore

build_script:
  - msbuild .\AspNetApplication\AspNetApplication.csproj /nologo /verbosity:m /t:Build /t:pipelinePreDeployCopyAllFilesToOneFolder /p:_PackageTempDir="..\publish";AutoParameterizationWebConfigConnectionStrings=false;Configuration=Release
  - docker build -t %DOCKER_IMAGE_NAME% .

test_script:
  - ps: |
      $cid = docker run -d $env:DOCKER_IMAGE_NAME
      $hostip = docker inspect -f "{{ .NetworkSettings.Networks.nat.IPAddress }}" $cid
      curl "http://${hostip}" -UseBasicParsing

deploy_script:
  - docker login -u %DOCKER_USER% -p %DOCKER_PASS%
  - docker push %DOCKER_IMAGE_NAME%
  - kubectl set image deployment/aspnet aspnet=%DOCKER_IMAGE_NAME% --server=%KUBE_MASTER% --token=%KUBE_TOKEN% --insecure-skip-tls-verify=true

kubectl は curl でダウンロードするだけなので簡単です。現在のデプロイメントに対してイメージを更新するコマンドは kubectl set image になります。

オプションとして --server と --token を追加して、Kubernetes のマスターの URL とさっき作成したトークンを渡します。証明書の検証が問題になるので --insecure-skip-tls-verify=true を指定してスキップします。

AppVeyor で実際にビルド

appveyor.yml の修正を GitHub にコミットして、実際に AppVeyor でビルドを行いました。kubectl の実行結果から成功したことが分かります。たったこれだけでアップデートが行われます。

f:id:shiba-yan:20170503211728p:plain

アップデート中にダッシュボードを確認すると、新しいレプリカセットとポッドが作成されています。

既にベースイメージは pull されているので、コンテナの起動は非常に高速です。

f:id:shiba-yan:20170503211656p:plain

アップデートが完了したら、ブラウザで外部エンドポイントにアクセスしてみます。アプリケーションに違いがないと、本当にアップデートが行われたのか確認しにくいので、テキストを少しだけ変えておきました。

例によって Razor のプリコンパイルを行っていないので、起動に少し時間がかかりますが表示されます。拍子抜けするぐらいあっさりと AppVeyor からのデプロイが行えました。

f:id:shiba-yan:20170503211807p:plain

ちなみに GitHub に push してから AppVeyor でのビルドが完了するまで 2 分ほどです。Docker Hub よりネットワーク的に近い Azure Container Registry を使うと pull は早くなりそうです。

今回は 1 エージェントかつ 1 レプリカで試しましたが、Kubernetes はまだ VMSS に対応していないみたいなので、エージェントを増やす手間がかかります。レプリカに関しては別の機会にまとめます。