Docker Enterprise の Kubernetes にWindows Workerノードを追加する #docker #mirantis #kubernetes #k8s
この記事は1年以上前に投稿されました。情報が古い可能性がありますので、ご注意ください。
本ブログは Mirantis社のblog記事「Windows Worker Nodes for Docker Enterprise Kubernetes: Easily add and scale Windows workload capacity」の翻訳記事です。
Docker Enterprise 3.1 の Kubernetes 1.17 では、Windows Worker ノードを簡単にクラスタに追加できます(クラスタの Master ノードは Linux 上で動作する必要があります)。新しく結合されたWindows Workerノード は Docker Enterprise の Kubernetes によって即座に認識され、deployment YAML の spec 内の nodeSelector に従ってワークロードをスケジューリングできます。
この Windows ベースのコンテナをオーケストレーションする機能の追加によって、Windows コンテナ形式のコンポーネントを幅広く活用する事が可能となり、Windows でのアプリケーションの開発や、アプリケーションのモダナイズを効率化し推進することが可能となります。
これにより、可用性を保証しスケーリングを促進するとともに、使い慣れた Windows 環境においても、コンテナ化やミッションクリティカル(またはレガシーな)Windowsアプリケーションの運用が比較的容易になります。もちろん、Azure Stack や Windows Server の仮想およびベアメタルインフラを提供する他のクラウドプラットフォームなども利用可能です。
Windows Server Worker ノードの設定
Windows Server の Workerノードをクラスタへ追加する前に、もちろんクラスタ自体を用意しなければなりません。クラスタを構築していない場合は、Getting Started Blog(日本語訳)を参照してクラスタを構築してください。
次に Windows Server ノードを作成し、そこに Docker Enterprise 3.1 のソフトウェアを設定してクラスタに追加するための準備を行います。
以下の手順では、PowerShell を管理者権限で実行して、Docker Enterprise 3.1 で Kubernetes ワーカーとして使用するための Windows Server 2019 の設定を詳細に説明します。クラウドホストを使用する場合は、コンテナ用にあらかじめ設定されたイメージではなく、Windows Server 2019 の OS イメージを選択してください。
Windows コンテナ機能を有効にしてから再起動します。改行をマークするためにバッククォートが使われていることに注意してください。
Enable-WindowsOptionalFeature ` -All ` -FeatureName containers ` -Online;
その後、必要に応じてコンピュータを再起動します。
Restart-Computer;
再起動後、リモートでダウンロードしたスクリプトを現在のセッションで実行できるように実行ポリシーを設定します。
Set-ExecutionPolicy ` -ExecutionPolicy RemoteSigned ` -Force ` -Scope Process;
次に、インストール用スクリプトをダウンロードします。
Invoke-WebRequest ` -OutFile 'install.ps1' ` -Uri 'https://get.mirantis.com/install.ps1' ` -UseBasicParsing;
そして、ダウンロードしたスクリプトを実行します。
.\install.ps1 -Channel 'test' -dockerVersion '19.03.8';
スクリプトの実行後、パスを更新するために一度ログアウトしてから再度ログインする必要があります。
logoff
再度ログインして、インストール用スクリプトを削除します。
Remove-Item -Path 'install.ps1';
この初期設定後、UCP イメージをダウンロードしてローカルの Docker リポジトリに保存します。
PowerShell のステータスバーをオフにすると、ダウンロード速度が向上します。
$ProgressPreference = 'SilentlyContinue'
そして、UCP のイメージバンドルをダウンロードします。
Invoke-WebRequest ` -OutFile 'ucp_images.tar.gz' ` -Uri 'https://packages.docker.com/caas/ucp_images_win_2019_3.3.0.tar.gz' ` -UseBasicParsing;
ダウンロード後、イメージバンドルをリポジトリにロードします。
docker load --input 'ucp_images.tar.gz';
イメージを参照して登録されているか確認します。
docker images;
最後に、ダウンロードしたイメージバンドルのアーカイブを削除します。
Remove-Item -Path 'ucp_images.tar.gz';
この時点で、クラスタにノードを追加するために必要な「 docker join 」コマンドを Docker Enterprise の UI から取得できます。 このコマンドは、Managerノードコンソールから " docker swarm join-token worker "を実行する事でも取得できます。これを新しく追加する Windows Workerノード の PowerShell コマンドラインにコピーして実行します。コマンドを実行した Worker ノードは Docker Enterprise によって Windows Worker ノードとして認識され、ノードリストに表示されます。
新しいノードを Kubernetes Worker として追加するように Docker Enterprise を設定している場合(Admin Settings の Orchestration で設定)、新しいノードは Kubernetes Worker として起動されます。デフォルトでは「 swarm 」として設定されています。 Kubernetes に切り替えるには、Manager ノードのコンソールから以下のコマンドを実行します。
docker node update <nodename> --label-add com.docker.ucp.orchestrator.kubernetes=true docker node update <nodename> --label-rm com.docker.ucp.orchestrator.swarm
動作を確認してみましょう
簡単なテストデプロイを実行してみましょう。
この例では、ロードバランサの後ろに2つの Pod を持つ Windows ウェブサーバをデプロイしています。デプロイするには、アカウント用に Docker Enterprise の UI からダウンロードした Client Bundle の env.sh スクリプトを使って " kubectl " をマシンにインストールし、 Docker Enterprise クラスタに認証する必要があります。詳しくは Getting Started Blog(日本語訳)を参照してください。
以下のコードは、Kubernetesのドキュメントで紹介されているものと同じです。
はじめに、作業用の namespace を作成します。
次の内容で demo-namespace.yaml を作成します。
# demo-namespace.yaml apiVersion: v1 kind: Namespace metadata: name: demo
作成した yaml ファイルを使って namespace を作成します。
kubectl create -f demo-namespace.yaml
次の内容で win-webserver.yaml を作成します。
この YAML にはウェブサーバを設定する組み込みコマンドが含まれており、応答するウェブサーバが実行されている Pod の IP を識別することで、リクエスト (この場合はポート 80 で起動している service の IP アドレス) に応答するアプリを作成していることに注意してください。このアプリはロードバランシングの確認に使用します。
# win-webserver.yaml apiVersion: v1 kind: Service metadata: name: win-webserver namespace: demo labels: app: win-webserver spec: ports: # the port that this service should serve on - port: 80 targetPort: 80 selector: app: win-webserver type: NodePort --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: win-webserver namespace: demo name: win-webserver namespace: demo spec: replicas: 2 selector: matchLabels: app: win-webserver template: metadata: labels: app: win-webserver name: win-webserver spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - win-webserver topologyKey: "kubernetes.io/hostname" containers: - name: windowswebserver image: mcr.microsoft.com/windows/servercore:ltsc2019 command: - powershell.exe - -command - "<#code used from https://gist.github.com/wagnerandrade/5424431#> ; $$listener = New-Object System.Net.HttpListener ; $$listener.Prefixes.Add('http://*:80/') ; $$listener.Start() ; $$callerCounts = @{} ; Write-Host('Listening at http://*:80/') ; while ($$listener.IsListening) { ;$$context = $$listener.GetContext() ;$$requestUrl = $$context.Request.Url ;$$clientIP = $$context.Request.RemoteEndPoint.Address ;$$response = $$context.Response ;Write-Host '' ;Write-Host('> {0}' -f $$requestUrl) ; ;$$count = 1 ;$$k=$$callerCounts.Get_Item($$clientIP) ;if ($$k -ne $$null) { $$count += $$k } ;$$callerCounts.Set_Item($$clientIP, $$count) ;$$ip=(Get-NetAdapter | Get-NetIpAddress); $$header='<html><body><H1>Windows Container Web Server</H1>' ;$$callerCountsString='' ;$$callerCounts.Keys | % { $$callerCountsString+='<p>IP {0} callerCount {1} ' -f $$ip[1].IPAddress,$$callerCounts.Item($$_) } ;$$footer='</body></html>' ;$$content='{0}{1}{2}' -f $$header,$$callerCountsString,$$footer ;Write-Output $$content ;$$buffer = [System.Text.Encoding]::UTF8.GetBytes($$content) ;$$response.ContentLength64 = $$buffer.Length ;$$response.OutputStream.Write($$buffer, 0, $$buffer.Length) ;$$response.Close() ;$$responseStatus = $$response.StatusCode ;Write-Host('< {0}' -f $$responseStatus) } ; " nodeSelector: beta.kubernetes.io/os: windows
このYAMLファイルをデプロイします。
kubectl create -f win-webserver.yaml
デプロイした service の動作を確認します。
kubectl get service --namespace demo
※ コマンド出力例
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE win-webserver NodePort 10.96.29.12 <none> 80:35048/TCP 12m
コマンドの実行結果として service のIPアドレスが表示されます。ブラウザでアクセスするとアプリの画面が表示されます。
service のIPアドレスをcurlで何度か連続して呼び出して見てください。
curl 10.96.29.12
アプリが2つの異なるIPアドレスを持つ2つの Pod にデプロイされ、受信するリクエストが負荷分散されていることを確認してください。
最後に service と namespace を削除してください。
kubectl delete service win-webserver kubectl delete namespace demo
これで Windows Worker ノードを追加してアプリをデプロイ出来ました。