Skip to content

Latest commit

 

History

History
524 lines (399 loc) · 20.6 KB

readme.md

File metadata and controls

524 lines (399 loc) · 20.6 KB

Running a Heterogeneous Azure-hosted Swarm Cluster

with both Linux and Windows nodes

Introduction

This tutorial will show you how to build an Azure-hosted Swarm cluster including both a Linux node and a Windows node, then deploy and run an application comprising Linux and Windows Containers on the Swarm.

It demonstrates using a Docker client running on Windows to interact with the Swarm cluster, utilizing the Azure CLI to provision the Swarm manager and node host VMs. The same approach may be used on Mac OS X or Linux, since the Azure CLI is available on those platforms as well.

Here is the sequence of steps you'll follow:

  1. Install Prerequisites

  2. Provision Swarm cluster VM hosts, build and push Images to Registry

  3. Create Swarm cluster comprising Linux and Windows nodes

  4. Run heterogeneous Linux / Windows application on Swarm cluster

Application Description and Architecture

The Bike Commuter Weather App is intended for bicycle commuters, for whom wind speed and direction are critical parameters - many weather apps leave this out or de-emphasize it. The architecture looks like this:

  • Web UI: ASP.NET 4.6 application hosted in a Docker Windows Container
  • Backend Web Service: Python REST web service, wrapping a weather service, hosted in a Docker Linux Container

App Diagram

Install Prerequisites

Install Chocolatey package manager for Windows

Install the "chocolatey" installation package manager, which provides a similar experience to package managers on Linux and Mac OS X.

Open an Admin command prompt:

> @powershell -NoProfile -ExecutionPolicy unrestricted -Command "(iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))) >$null 2>&1" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin

Install Git

> choco install git -y

Install npm package manager

Use npm to install Azure CLI (the same approach is used with Mac OS X and Linux, if you should choose to use one of those as your client platform):

> choco install nodejs.install -y

Install openssl and other Unix utilities

Since openssl and other Unix utilities are referenced by Azure CLI, install Cygwin and its package manager cyg-get:

> choco install cygwin -y
> choco install cyg-get -y
> cyg-get openssh

Install Azure CLI

Open "Cygwin64 Terminal" from the desktop icon and use it for all remaining commands.

$ npm install azure-cli -g

Install Docker client via Docker Toolbox

For Windows or Mac OS X, you'll use Docker Toolbox to install the Docker client (on Linux, you would instead install the Docker Engine).

Navigate to Docker Toolbox to download and run the installer.

Provision Swarm cluster VM hosts, build and push Images to Registry

If you don't have an Azure account, you can get a 30-day trial with a $200 credit - this requires a credit card to sign-up, but the card will not be charged for the first month's usage.

Login using Azure subscription credentials

Substitute your Azure Account Id for yourAzureAccountId below:

$ azure login yourAzureAccountId

You'll see a code in the command line window - as the on-screen instructions say, go to aka.ms/devicelogin and enter the code.

Optional: If you have more than one Azure subscription associated with the account, specify the subscription to use in subsequent commands as follows, substituting the subscription id (from the Azure portal) for yourDefaultAzureSubscriptionId below:

$ azure account set yourDefaultAzureSubscriptionId

Change mode to ARM (Azure Resource Manager):

$ azure config mode arm

Create a resource group which will contain all the resources for the Swarm cluster:

$ azure group create -n "cliEastUsSwarmRG" -l "East US"

Provision VM host for Windows Swarm node using Azure ARM template

You'll provision the Windows Swarm node first using an ARM template, since Windows is not yet fully supported by the Azure CLI "azure vm docker create" command. The "cli-win-node_subnet" created by this provisioning step is subsequently used by the Linux VM provisioning steps.

You'll need to substitute a unique node name for the "dnsNameForPublicIP" parameter before running the following command in place of uniqueWindowsNodeName, such as "myname-win-node" - this step can take up to 20 minutes to complete:

$ azure group deployment create cliEastUsSwarmRG cli-win-node --template-uri https://raw.githubusercontent.com/docker/labs/master/windows/dotnet-aspnet46-webapp/azuredeploy.json -p '{"adminUsername": {"value": "Azure123"}, "adminPassword": {"value": "Azure!23"}, "dnsNameForPublicIP": {"value": "uniqueWindowsNodeName"}, "VMName": {"value": "cli-win-node"},"location": {"value": "East US"}}'

Provision VM host for Swarm Manager and Registry using Azure docker create

Below you will create the Swarm manager VM with its own NIC, Public IP Address and a new storage account, sharing the Windows VM host subnet created earlier. Ubuntu is used in this tutorial for the Linux VMs.

This step can take up to 15 minutes to complete.

$ azure vm docker create --resource-group cliEastUsSwarmRG --name cli-swarm-master -l "East US" --os-type linux --nic-name clitestnic --public-ip-name clitestpip --vnet-name cli-win-node_vnet --vnet-subnet-name cli-win-node_subnet --storage-account-name cliswarmstorageacct --vnet-address-prefix 10.0.0/16  --vnet-subnet-address-prefix 10.0.0/24 --image-urn canonical:UbuntuServer:14.04.4-LTS:14.04.201602220 --admin-username Azure123 --admin-password 'Azure!23'

When prompted for "public IP domain name", provide a uniqueManagerName that will be unique in the eastus.cloudapp.azure.com DNS namespace, such as "myname-manager"

This will be DNS-accessible as uniqueManagerName.eastus.cloudapp.azure.com

Configure Manager VM host Docker Engine startup options

For the purposes of this tutorial, you will disable TLS for the entire swarm, since TLS is not working with the Windows Docker Engine as of TP5.

For uniqueManagerName below, substitute the name you supplied above, such as "myname-manager":

$ ssh uniqueManagerName.eastus.cloudapp.azure.com -l Azure123

Use password Azure!23 when prompted.

The first time you connect via ssh, you'll see a message saying "The authenticity of host... can't be established... Are you sure you want to continue connecting (yes/no)?" - answer Yes

Remove TLS entries from docker daemon config and specify insecure registry.

For uniqueManagerName below, substitute the name you supplied above, such as "myname-manager":

$ sudo bash
# sed -i -r 's/(DOCKER_OPTS\s*=\s*)\"([^"]+)\"/DOCKER_OPTS="\-H=unix\:\/\/ -H=0\.0\.0\.0\:2376 --insecure-registry uniqueManagerName.eastus.cloudapp.azure.com\:5000\"/g' /etc/default/docker
# service docker restart
# exit

Set up local Docker Registry

In order to utilize the Label-based deployment described in [Run heterogeneous Linux / Windows application on Swarm cluster] (#run-heterogeneous-linux--windows-application-on-swarm-cluster) below, you'll need a Docker registry.

You'll set up a local Docker Registry, sharing the same host VM as the Swarm Manager.

Note in many use cases you can just use Docker Hub instead of setting up a registry

$ docker run -d -p 5000:5000 --restart=always --name registry -v `pwd`/registry:/var/lib/registry registry:2
$ exit

Provision VM host for Linux Swarm node, build and push App Linux Image to Registry

As for the Swarm Manager, you'll use Ubuntu:

This step can take up to 15 minutes to complete.

$ azure vm docker create --resource-group cliEastUsSwarmRG --name cli-linux-node -l "East US" --os-type linux --nic-name clitestnic-linux-node --public-ip-name clitestpip-linux-node --vnet-name cli-win-node_vnet --vnet-subnet-name cli-win-node_subnet --storage-account-name cliswarmstorageacct --vnet-address-prefix 10.0.0/16  --vnet-subnet-address-prefix 10.0.0/24 --image-urn canonical:UbuntuServer:14.04.4-LTS:14.04.201602220 --admin-username Azure123 --admin-password 'Azure!23'

When prompted for "public IP domain name", provide a uniqueLinuxNodeName that will be unique in the eastus.cloudapp.net DNS namespace, such as "myname-linux-node"

Configure Linux node VM Docker Engine startup options

For uniqueLinuxNodeName below, substitute the name you supplied above, such as "myname-linux-node":

$ ssh uniqueLinuxNodeName.eastus.cloudapp.azure.com -l Azure123

Use password Azure!23 when prompted.

Remove TLS entries from docker daemon config and specify insecure registry.

For uniqueManagerName below, substitute the name you supplied above, such as "myname-manager":

$ sudo bash
# sed -i -r 's/(DOCKER_OPTS\s*=\s*)\"([^"]+)\"/DOCKER_OPTS="\-H=unix\:\/\/ -H=0\.0\.0\.0\:2375 --insecure-registry uniqueManagerName.eastus.cloudapp.azure.com\:5000 --label ostypelabel=linuxcompat\"/g' /etc/default/docker
# service docker restart
# exit

Get Linux Swarm node advertise IP

Save the "eth0: inet addr" below for later use as linuxNodeAdvertiseIP:

$ ifconfig

eth0      Link encap:Ethernet  HWaddr 00:0d:3a:12:16:7f
          inet addr:linuxNodeAdvertiseIP  Bcast:10.0.0.255  Mask:255.255.255.0
          inet6 addr: fe80::20d:3aff:fe12:167f/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:267865 errors:0 dropped:0 overruns:0 frame:0
          TX packets:81890 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:321904571 (321.9 MB)  TX bytes:202479327 (202.4 MB)

Build App Linux Image

$ git clone https://github.com/docker/labs.git
$ docker build -t rushhourweatherappservice labs/windows/Python-REST-Service

Push App Linux Image to Registry

For uniqueManagerName below, substitute the name you supplied above, such as "myname-manager":

$ docker tag rushhourweatherappservice uniqueManagerName.eastus.cloudapp.azure.com:5000/rushhourweatherappservice
$ docker push uniqueManagerName.eastus.cloudapp.azure.com:5000/rushhourweatherappservice
$ exit

Finish provisioning VM for Windows Swarm node, build and push App Windows Image to Registry

Configure Windows node VM Docker Engine startup options

Remote Desktop: uniqueWindowsNodeName.eastus.cloudapp.azure.com

Username: .\Azure123

Password: Azure!23

For uniqueManagerName below, substitute the name you supplied above, such as "myname-manager":

   > powershell
PS > (cat c:\programdata\docker\runDockerDaemon.cmd) | % { $_ -replace “-H 0.0.0.0:2375”,”-H 0.0.0.0:2375 --insecure-registry uniqueManagerName.eastus.cloudapp.azure.com:5000 --label ostypelabel=windowscompat” } | set-content c:\programdata\docker\runDockerDaemon.cmd
PS > restart-service docker

Get Windows Swarm node advertise IP

Save the "Ethernet adapter Ethernet 2: IPv4 Address" below for later use as windowsNodeAdvertiseIP:

PS > ipconfig

Ethernet adapter Ethernet 2:

   Connection-specific DNS Suffix  . : wehxhlhuqqvuxh2wpb4ezkbuof.bx.internal.cloudapp.net
   Link-local IPv6 Address . . . . . : fe80::81be:578e:4eb:3e2a%6
   IPv4 Address. . . . . . . . . . . : windowsNodeAdvertiseIP
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 10.0.0.1

Build Windows Swarm Image

PS > choco install git -y
PS > $env:PATH = "$env:PATH;c:\program files\git\cmd"
PS > git clone https://github.com/docker/labs.git
PS > cd labs\windows
PS > docker build -t swarm swarm-windows

Build App Windows Image

PS > docker build -t rushhourweatherappui dotnet-aspnet46-webapp

Push App Windows Image to Registry

For uniqueManagerName below, substitute the name you supplied above, such as "myname-manager":

PS > docker tag rushhourweatherappui uniqueManagerName.eastus.cloudapp.azure.com:5000/rushhourweatherappui
PS > docker push uniqueManagerName.eastus.cloudapp.azure.com:5000/rushhourweatherappui

Create Swarm cluster comprising Linux and Windows nodes

You'll use the docker client on your workstation to create the Swarm cluster. The sequence of steps is:

  1. Create Swarm cluster id on the Manager host

  2. Join Linux node to the Swarm cluster, specifying the cluster id

  3. Join Windows node to the Swarm cluster, specifying the cluster id

  4. Start Swarm Manager on the manager host

Create Swarm cluster id

For uniqueManagerName below, substitute the name you supplied above, such as "myname-manager":

$ docker -H tcp://uniqueManagerName.eastus.cloudapp.azure.com:2376 run --rm swarm create

The cluster id is the guid code which is output at the end of the above command - save this as you will need it later on, referred to as myClusterId.

Join Linux node to Swarm cluster

For uniqueLinuxNodeName below, substitute the unique Linux host name you recorded above, for linuxNodeAdvertiseIP below, the IP address, and for myClusterId, the cluster id:_

$ docker -H tcp://uniqueLinuxNodeName.eastus.cloudapp.azure.com:2375 run -d swarm join --advertise=linuxNodeAdvertiseIP:2375 token://myClusterId

Join Windows node to Swarm cluster

For uniqueWindowsNodeName below, substitute the unique Windows host name you recorded above, for windowsNodeAdvertiseIP, the IP address, and for myClusterId, the cluster id:

$ docker -H tcp://uniqueWindowsNodeName.eastus.cloudapp.azure.com:2375 run -d swarm join --advertise=windowsNodeAdvertiseIP:2375 token://myClusterId

Start Swarm Manager

For uniqueManagerName below, substitute the unique manager name you recorded above, and for myClusterId, the cluster id:

$ docker -H tcp://uniqueManagerName.eastus.cloudapp.azure.com:2376 run -d -p 2375:2375 swarm manage token://myClusterId

Set SWARM_HOST environment variable on the workstation so that subsequent docker client commands default to using the Swarm Manager.

For uniqueManagerName below, substitute the name you supplied above, such as "myname-manager":

$ export DOCKER_HOST=uniqueManagerName.eastus.cloudapp.azure.com:2375

List the nodes - you should see something like the excerpt below, showing both Linux and Windows nodes up. You'll sometimes need to wait up to 1 minute for the service discovery process to complete, and both nodes to appear:

$ docker info

Nodes: 2
 cli-linux-node: linuxNodeAdvertiseIP:2375
   Status: Healthy
   Containers: 1
   Reserved CPUs: 0 / 1
   Reserved Memory: 0 B / 1.719 GiB
   Labels: executiondriver=native-0.2, kernelversion=3.19.0-51-generic, operatingsystem=Ubuntu 14.04.4 LTS, ostypelabel=linuxcompat, storagedriver=aufs
   Error: (none)
   UpdatedAt: 2016-03-06T19:16:49Z
 cli-win-node: windowsNodeAdvertiseIP:2375
   Status: Healthy
   Containers: 1
   Reserved CPUs: 0 / 1
   Reserved Memory: 0 B / 3.675 GiB
   Labels: executiondriver=
 Name: Windows 1854
 Build: 1.10.0-dev 18c9fe0
 Default Isolation: process, kernelversion=10.0 10586 (10586.0.amd64fre.th2_release.151029-1700), operatingsystem=Windows Server 2016 Technical Preview 4, ostypelabel=windowscompat, storagedriver=windowsfilter
   Error: (none)
   UpdatedAt: 2016-03-06T19:16:53Z

Run heterogeneous Linux / Windows application on Swarm cluster

List the available Images from the local Docker Registry

Navigate to the following in a web browser - you'll see a "repository" for each of the Images -

For uniqueManagerName below, substitute the name you supplied above, such as "myname-manager":

http://uniqueManagerName.eastus.cloudapp.azure.com:5000/v2/_catalog

{"repositories":["rushhourweatherappservice","rushhourweatherappui"]}

Run App REST web service in a Linux Container on the Swarm cluster

For uniqueManagerName below, substitute the name you supplied above, such as "myname-manager"; for yourWundergroundApiKey, a weatherunderground api key (note the demo application will run without this key, displaying an error message that the key is required):

$ docker run --name rushhourweatherappservice -d -p 5000:5000 -e constraint:ostypelabel==linuxcompat -e WUNDERGROUND_API_KEY=yourWundergroundApiKey uniqueManagerName.eastus.cloudapp.azure.com:5000/rushhourweatherappservice

Run App Web UI in a Windows Container on the Swarm cluster

For uniqueManagerName below, substitute the manager host name you supplied above, for uniqueLinuxNodeName, the linux node name:

$ docker run --name rushhourweatherappui -d -p 80:80 -e WeatherServiceUrl=http://uniqueLinuxNodeName.eastus.cloudapp.azure.com:5000 -e constraint:ostypelabel==windowscompat uniqueManagerName.eastus.cloudapp.azure.com:5000/rushhourweatherappui

Inspect the Swarm

$ docker ps

CONTAINER ID        IMAGE                                                                         COMMAND                  CREATED                  STATUS                  PORTS                          NAMES
e6082d708dfa        uniqueManagerName.eastus.cloudapp.azure.com:5000/rushhourweatherappservice   "python /tmp/public-s"   Less than a second ago   Up Less than a second   40.121.85.244:5000->5000/tcp   cli-linux-node/rushhourweatherappservice
e69ad82ac726        uniqueManagerName.eastus.cloudapp.azure.com:5000/rushhourweatherappui        "cmd /S /C powershell"   About an hour ago        Up About an hour                                       cli-win-node/rushhourweatherappui

$ docker info

Containers: 4
 Running: 4
 Paused: 0
 Stopped: 0
Images: 7
Server Version: swarm/1.1.3
Role: primary
Strategy: spread
Filters: health, port, dependency, affinity, constraint
Nodes: 2
 cli-linux-node: linuxNodeAdvertiseIP:2375
   Status: Healthy
   Containers: 2
   Reserved CPUs: 0 / 1
   Reserved Memory: 0 B / 1.719 GiB
   Labels: executiondriver=native-0.2, kernelversion=3.19.0-51-generic, operatingsystem=Ubuntu 14.04.4 LTS, ostypelabel=linuxcompat, storagedriver=aufs
   Error: (none)
   UpdatedAt: 2016-03-06T21:32:29Z
 cli-windows-node: windowsNodeAdvertiseIP:2375
   Status: Healthy
   Containers: 2
   Reserved CPUs: 0 / 1
   Reserved Memory: 0 B / 3.675 GiB
   Labels: executiondriver=
 Name: Windows 1854
 Build: 1.10.0-dev 18c9fe0
 Default Isolation: process, kernelversion=10.0 10586 (10586.0.amd64fre.th2_release.151029-1700), operatingsystem=Windows Server 2016 Technical Preview 4, ostypelabel=windowscompat, storagedriver=windowsfilter
   Error: (none)
   UpdatedAt: 2016-03-06T21:32:33Z
Plugins:
 Volume:
 Network:
Kernel Version: 3.19.0-51-generic
Operating System: linux
Architecture: amd64
CPUs: 2
Total Memory: 5.394 GiB
Name: d73f6f2cf088

Try out the running application on the Swarm cluster

For uniqueWindowsNodeName and uniqueLinuxNodeName below, substitute the names you supplied above, such as "myname-win-node" and "myname-linux-node".

Try out the Web UI application from a web browser - navigate to:

http://uniqueWindowsNodeName.eastus.cloudapp.azure.com/RushHourWeatherApp

The Web UI Windows application consumes the Linux service - you can directly examine the Linux service by navigating to:

http://uniqueLinuxNodeName.eastus.cloudapp.azure.com:5000/today/amrush

Credits