Displaying present location in the site.

We Tried Building an HA Cluster for Docker Container (Windows): Part 1/2

EXPRESSCLUSTER Official Blog

May 11th, 2023

Machine translation is used partially for this article. See the Japanese version for the original article.

Introduction

We tried building an HA cluster for an application in Docker container. By starting, stopping, and monitoring Docker containers from EXPRESSCLUSTER, Docker applications can be easily made redundant with a small number of nodes to improve availability. Please refer to this article when HA clustering is required in cases where applications are provided only in Docker container format.

As the application in Docker container to be run this time, we will use the online storage software "Nextcloud" and "PostgreSQL" for its database. Also, we install Windows Subsystem for Linux (hereinafter called "WSL").

This article is divided into two parts: "Part 1", which performs everything from the advance preparation in the Windows environment to creation of Docker container, and "Part 2", which configures EXPRESSCLUSTER settings for Docker services and container control. This time, we will introduce "Part 1". For "Part 2", please refer to popuphere.

  • *Note
    Because of the cause that is probably same as the issue below, we have confirmed the problem that the execution of the wsl command described in this article fails depending on the environment. Therefore, it may not be possible to execute the wsl command in the EXPRESSCLUSTER script resource.

Contents

1. About Docker

1.1 What is Docker?

Docker is one of the container-based virtualization that creates and manages an isolated execution environment called a container.

Unlike hypervisor-based virtualization, Docker does not require the creation of virtual machines. Docker also features faster container startup and processing than virtual machines. The advantage of Docker is that it can be easily deployed and run if you have a container image of the middleware or application you want to run, without having to install it on a physical server.

1.2 Points to Note When Using Docker on Windows

Docker can be used in Linux, Mac, and Windows environments. When using in the Windows environment, WSL must be installed. Also, when using Docker and WSL in the Windows environment, you need to be aware of the following:

  • WSL has WSL1 and WSL2. In this article, we will use WSL2.
  • To use WSL2, the virtualization must be enabled on the Windows Server where you are installing. You can check whether the virtualization is enabled by running the following command in PowerShell. If "VirtualizationFirmwareEnabled" is "True" in the command execution result, the virtualization is enabled.
    > Get-WmiObject -Class Win32_Processor | Format-List VirtualizationFirmwareEnabled

    VirtualizationFirmwareEnabled : True ★Display the number of CPUs.
  • In order to enable the virtualization, you may need to configure UEFI/BIOS or Hyper-V on the host to be virtualized.
  • It is possible to mount an NTFS file system on the Windows side within WSL2, but it is not used in this article. Instead, create a virtual disk file on an NTFS file system, format it with an ext4 file system, and mount it within WSL2.
    The reason is that when an NTFS file system is mounted on a Docker container, the mount point is fixed with full access (mode is 777), and some applications in Docker container such as Nextcloud fail to operation properly due to errors caused by permissions.
  • Ports exposed externally in Docker containers cannot be accessed from outside Windows Server as they are. This is due to Docker running on Ubuntu in WSL2 instead of Windows Server. Therefore, it is necessary to separately configure port forwarding settings between Windows Server and Ubuntu in WSL2 with netsh commands.

1.3 Points to Note When Using Docker from EXPRESSCLUSTER

When using Docker from EXPRESSCLUSTER X for Windows, the following points should be noted.

  • If the automount feature of WSL2 (which automatically mounts Windows drives in WSL2 when WSL2 starts) is enabled, it is recommended that the automount feature is disabled. Because every time WSL2 is started, an error related to the cluster partition of the mirror disk will occur.
  • The local system account (SYSTEM), which is the default user to execute the script resources or the custom monitor resources of EXPRESSCLUSTER X, cannot run the wsl commands. It must be run as the Administrator user (specify [Administrator] as the [Exec User] for each resource).
In this article, we will introduce the configuration procedure combined with EXPRESSCLUSTER X based on these points.

2. HA Cluster Configuration

The HA cluster to build this time is the Active-Standby configuration.

Switching between the active and the standby server is performed by FIP (floating IP) in this article, but switching can also be performed by VIP (virtual IP) or DNS according to requirements.

■Network / Hardware

  • Network
  • - Network address : 172.16.1.0/24
  • - Floating IP address : 172.16.1.100
  • Servers for HA cluster
  • - server1
  • - IP address : 172.16.1.11
  • - Disk1 (for OS) : 40GiB
  • - Disk2 (for mirror disk) : 30GiB
  • - server2
  • - IP address : 172.16.1.21
  • - Disk1 (for OS) : 40GiB
  • - Disk2 (for mirror disk) : 30GiB

■OS / EXPRESSCLUSTER

  • EXPRESSCLUSTER X 5.1 for Windows (Internal Ver. 13.10)
  • Windows Server 2022 (*)

  • *We can use Windows that has been confirmed to operation with EXPRESSCLUSTER and that is supported by WSL2.
[Reference]
popupSystem Requirements - EXPRESSCLUSTER X for Windows
  • EXPRESSCLUSTER X 5.1
  • -> EXPRESSCLUSTER Server

Also, please refer to the Getting Started Guide for EXPRESSCLUSTER X system requirements and mirror disk requirements.

[Reference]
popupDocumentation - Manuals
  • EXPRESSCLUSTER X 5.1 > EXPRESSCLUSTER X 5.1 for Windows > Getting Started Guide
  • -> 4 Installation requirements for EXPRESSCLUSTER
  • -> 6 Notes and Restrictions
  • -> 6.1 Designing a system configuration
  • -> 6.1.1 Hardware requirements for mirror disk and hybrid disk

The relationship between EXPRESSCLUSTER X, Docker service, container and mirror disk is shown in the following image.

Install WSL2 and Docker on Windows Server 2022 and put two containers, PostgreSQL and Nextcloud. Each container is started and stopped by the script resources of EXPRESSCLUSTER. In addition, various monitor resources are used to perform alive monitoring for Docker services and containers.
Although PostgreSQL can be operated by directly installing a Windows version of the application instead of a Docker container version, the container version is used in this article as an example of cooperation between Docker containers.
Nextcloud provides an online storage service that allows users to share files using a web browser. In this article, a DB container for PostgreSQL running on the same Docker is used as the data storage destination.

To mirror the data of PostgreSQL and Nextcloud containers between servers, a virtual disk is placed on mirror disk controlled in EXPRESSCLUSTER and data is stored in it.
For details on a mirror disk type cluster, please refer to the following article.

The final resource configuration of EXPRESSCLUSTER X is as follows.

■Resource configuration of EXPRESSCLUSTER

  • Failover group (failover1)
  • - Floating IP resource (fip1)
  • - Mirror disk resource (md-Docker)
  • - Script resource (script-DockerService)
  • - Script resource (script-VirtualDisk)
  • - Script resource (script-DockerDB)
  • - Script resource (script-DockerApp)

  • Monitor resources
  • - Floating IP monitor resource (fipw1)
  • - Mirror disk monitor resource (mdw-Docker)
  • - Custom monitor resource (genw-DockerService)
  • - Custom monitor resource (genw-VirtualDisk)
  • - PostgreSQL monitor resource(psqlw-DockerDB)
  • - Custom monitor resource (genw-DockerApp)
  • - User mode monitor resource (userw)

3. HA Cluster Building Procedure (Creating a Docker Container)

3.1 HA Cluster Preparation

Prepare two servers for the HA cluster.
Check that the virtualization is enabled on each server.

Installation of WSL2, Docker, and Nextcloud is done while downloading the necessary packages online. Therefore, the network must be properly configured so that each server can access the Internet.

3.2 Installing WSL2

This procedure is performed on both server1 and server2.

In this article, shell prompts are denoted by ">" for PowerShell and "$" for bash.

Start PowerShell and install WSL2 with the following command. Specify Ubuntu 20.04 as the distribution.

  • > wsl --install -d Ubuntu-20.04

After installation, you will be asked to restart the OS.
After the restart, when WSL2 starts, WSL2 will ask you to enter the default Ubuntu user and password, enter any string (in this article, we will use "wsluser").
Start PowerShell and check the WSL version. If the VERSION is set to 2 as shown below, you know that you are using WSL2.

  • > wsl --list --verbose
  • NAME         STATE         VERSION
  • * Ubuntu-20.04         Running         2

Edit the WSL2 configuration file (wsl.conf) to disable WSL2's Windows drive automount feature.

  • > wsl -e sudo vi /etc/wsl.conf

In the configuration file, enter and save the following settings.

  • [automount]
    enabled = false

Exit WSL2 once to reflect the settings in the configuration file.

  • > wsl --shutdown

3.3 Installing Docker

This procedure is performed on both server1 and server2.

Enter WSL2.

  • > wsl

Update the package.

  • $ sudo apt-get update
  • $ sudo apt-get upgrade

Register a Docker repository and install Docker.

  • $ sudo apt-get install ca-certificates curl gnupg lsb-release
  • $ sudo mkdir -p /etc/apt/keyrings
  • $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
  • $ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  • $ sudo apt-get update
  • $ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

  • *The above Docker installation procedure on Ubuntu is based on the following official Docker page.

Register the default user (wsluser) of WSL2 as a Docker administrator and make docker commands runnable.

  • $ sudo usermod -aG docker wsluser

For commands run by the default user of WSL2, when performing operations with sudo, allow them to be run without the sudo password. This is to eliminate the need to enter a password when running commands from a EXPRESSCLUSTER X resources.

  • $ echo "wsluser ALL=(ALL) NOPASSWD: /usr/sbin/service,/usr/bin/mount,/usr/bin/umount,/usr/bin/mountpoint" | sudo tee /etc/sudoers.d/expresscluster > /dev/null
  • $ exit

3.4 Building an HA Cluster

Install EXPRESSCLUSTER X on each of server1 and server2 and use the Cluster WebUI to build an HA cluster.

Add a floating IP resource and a mirror disk resource to the failover group. The mirror disk resource control the disk on which to put shared data of Docker containers.

  • Failover group (failover1)
  • - Floating IP resource (fip1)
  • - IP Address : 172.16.1.100
  • - Mirror disk resource (md-Docker)
  • - Cluster partition : L: (1024MiB)
  • - Data partition : M: (29GiB)

3.5 Creating a Virtual Disk for Docker Shared Data (server1)

Create a virtual disk on M drive (the data partition of the mirror disk) that will be used by the Docker container for external storage.

Using the Cluster WebUI, start the mirror disk resource (md-Docker) on server1.

Run the diskpart command on server1.

  • > diskpart

At the prompt of diskpart, run the following command to create a virtual disk "M:\nextcloud.vhdx" on drive M. The "maximum" parameter specifies the capacity of the virtual disk to be created, in MiB.

  • e.g. Create a 20GiB virtual disk.
  • DISKPART> create vdisk file="M:\nextcloud.vhdx" maximum=20480 type=expandable
  • DISKPART> exit

3.6 Mounting a Virtual Disk to WSL2 (server1)

Mount the virtual disk to make it accessible from Windows on server1.

  • > $ret = Mount-DiskImage M:\nextcloud.vhdx

To make the mounted virtual disk accessible to WSL2, recognize it with the wsl command.

  • > wsl --mount $ret.DevicePath --bare

Enter WSL2.

  • > wsl

Create a mount destination (/mnt/data) for the mounted virtual disk.

  • $ sudo mkdir /mnt/data

Run the lsblk command to check the device name of the virtual disk by size.
Since the virtual disk created this time is 20GiB, we can see that the device name is "sdc".

  • $ sudo lsblk
  • NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
  • sda 8:0 0 256G 0 disk
  • sdb 8:16 0 256G 0 disk /
  • sdc 8:32 0 20G 0 disk

Format the virtual disk for which the device name is known with the file system type ext4.

  • $ sudo mkfs -t ext4 /dev/sdc

Run the blkid command to obtain the UUID of the virtual disk.
The string that follows the "UUID=" is the UUID (in the example below, "aaaaaaaa-bbbb-cccc-ddddd-eeeeeeeeeeeeeeeeee").
Note down this UUID as it will be needed later when adding EXPRESSCLUSTER script resource.

  • $ sudo blkid -s UUID -o export /dev/sdc
  • DEVNAME=/dev/sdc
  • UUID=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee

Mount the virtual disk to "/mnt/data", specifying the UUID obtained.

  • $ sudo mount UUID=<UUID noted down> /mnt/data

3.7 Creating a PostgreSQL Container (server1)

Start the Docker service on server1.

Run the following command while in WSL2.

  • $ sudo service docker start

Create a PostgreSQL container with the name "nextcloud-db". Specify any DB password for "POSTGRES_PASSWORD".

  • $ sudo mkdir /mnt/data/nextcloud_db
  • $ docker run -d \
    --env POSTGRES_DB=nextcloud \
    --env POSTGRES_USER=nextcloud \
    --env POSTGRES_PASSWORD=xxxxxxxx \
    --mount type=bind,source=/mnt/data/nextcloud_db,target=/var/lib/postgresql/data \
    --restart no \
    --name nextcloud-db \
    -p 5432:5432 \
    postgres:15.1

3.8 Creating a Nextcloud Container (server1)

On server1, create a Nextcloud container with the name "nextcloud", where "POSTGRES_PASSWORD" is the same password specified in "3.7 Creating a PostgreSQL Container (server1)".

  • $ sudo mkdir /mnt/data/nextcloud_data
  • $ docker run -d \
    --env POSTGRES_HOST=nextcloud-db:5432 \
    --env POSTGRES_DB=nextcloud \
    --env POSTGRES_USER=nextcloud \
    --env POSTGRES_PASSWORD=xxxxxxxx \
    --mount type=bind,source=/mnt/data/nextcloud_data,target=/var/www/html \
    --restart no \
    --name nextcloud \
    --link nextcloud-db \
    -p 80:80 \
    docker.io/library/nextcloud
  • $ exit

Access "http://localhost/" from a web browser on server1 and check that the Nextcloud screen is displayed.

Next, run the following command in PowerShell to configure port forwarding so that HTTP accesses to the server's IP address are forwarded to the Nextcloud container's http port.

  • > $ip = wsl -e hostname -I | % {$_.Split(" ")[0]}; netsh interface portproxy add v4tov4 listenaddress=* listenport=80 connectaddress=$ip connectport=80
Access "http://172.16.1.100/" as the URL of the floating IP address from a web browser on server1 and check that the Nextcloud screen is displayed.

3.9 Stopping the Docker Container and Unmounting the Virtual Disk (server1)

Enter WSL2 on server1.

  • > wsl

Stop the Docker container and Docker service and unmount the virtual disk.

  • $ docker stop nextcloud
  • $ docker stop nextcloud-db
  • $ sudo service docker stop
  • $ sudo umount /mnt/data
  • $ exit

  • > wsl --shutdown
  • > Dismount-DiskImage M:\nextcloud.vhdx

Run the following command to move the EXPRESSCLUSTER failover group to server2.

  • > clpgrp -m failover1

3.10 Mounting a Virtual Disk to WSL2 (server2)

Mount the virtual disk to make it accessible from Windows on server2.

  • > $ret = Mount-DiskImage M:\nextcloud.vhdx

To make the mounted virtual disk accessible to WSL2, recognize it with the wsl command.

  • > wsl --mount $ret.DevicePath --bare

Enter WSL2.

  • > wsl

Mount the virtual disk to "/mnt/data", specifying the UUID you noted in "3.6 Mounting a virtual disk in WSL2 (server1)".

  • $ sudo mkdir /mnt/data
  • $ sudo mount UUID=<UUID noted down> /mnt/data

3.11 Creating a PostgreSQL Container (server2)

Start the Docker service on server2.

Run the following command while in WSL2.

  • $ sudo service docker start

Create a PostgreSQL container with the name "nextcloud-db", where "POSTGRES_PASSWORD" is the same password specified for server1.

  • $ docker run -d \
    --env POSTGRES_DB=nextcloud \
    --env POSTGRES_USER=nextcloud \
    --env POSTGRES_PASSWORD=xxxxxxxx \
    --mount type=bind,source=/mnt/data/nextcloud_db,target=/var/lib/postgresql/data \
    --restart no \
    --name nextcloud-db \
    -p 5432:5432 \
    postgres:15.1

3.12 Creating a Nextcloud Container (server2)

On server2, create a Nextcloud container with the name "nextcloud", where "POSTGRES_PASSWORD" is the same password specified in "3.11 Creating a PostgreSQL Container (server2)".

  • $ docker run -d \
    --env POSTGRES_HOST=nextcloud-db:5432 \
    --env POSTGRES_DB=nextcloud \
    --env POSTGRES_USER=nextcloud \
    --env POSTGRES_PASSWORD=xxxxxxxx \
    --mount type=bind,source=/mnt/data/nextcloud_data,target=/var/www/html \
    --restart no \
    --name nextcloud \
    --link nextcloud-db \
    -p 80:80 \
    docker.io/library/nextcloud
  • $ exit

Access "http://localhost/" from a web browser on server2 and check that the Nextcloud screen is displayed.

Next, run the following command in PowerShell to configure port forwarding so that HTTP accesses to the server's IP address are forwarded to the Nextcloud container's http port.

  • > $ip = wsl -e hostname -I | % {$_.Split(" ")[0]}; netsh interface portproxy add v4tov4 listenaddress=* listenport=80 connectaddress=$ip connectport=80
Access "http://172.16.1.100/" as the URL of the floating IP address from a web browser on server2 and check that the Nextcloud screen is displayed.

3.13 Stopping the Docker Container and Unmounting the Virtual Disk (server2)

Enter WSL2 on server2.

  • > wsl

Stop the Docker container and Docker service and unmount the virtual disk.

  • $ docker stop nextcloud
  • $ docker stop nextcloud-db
  • $ sudo service docker stop
  • $ sudo umount /mnt/data
  • $ exit

  • > wsl --shutdown
  • > Dismount-DiskImage M:\nextcloud.vhdx

Conclusion

This time, we introduced the procedure for installing WSL2 and Docker on the servers for HA cluster and creating a Docker container by put Docker data on a mirror disk.
In "Part 2", we will introduce the configuration procedure of EXPRESSCLUSTER X to start, stop, and monitor Docker services and Docker containers from EXPRESSCLUSTER X. Please refer to popup"Part 2" as well.

If you consider introducing the configuration described in this article, you can perform a validation with the popuptrial module of EXPRESSCLUSTER. Please do not hesitate to contact us if you have any questions.

  • * For support for software other than EXPRESSCLUSTER, please contact the respective vendor.