How to Deploy a JBoss Cluster with Ansible Pt. 1

Ansible helps you automate your infrastructure configuration so you can focus on building better software.

How to Deploy a JBoss Cluster with Ansible Pt. 1

Personally, I like to ride trains that don’t crash into other ones.

And our recent client, a transportation department who I'll call "Govgov", works to make sure that doesn't happen.

But when we arrived, they were spending a week setting up infrastructure for new environments. Which leaves less time to improve their product.

Or, less time to make sure you and I don’t wind up splattered on the tracks.

From One Week to One Hour

Ansible is an automation platform that helps us configure infrastructure in a fraction of the time. The platform contains three main things:

  • Inventory - The hosts to target
  • Playbooks - The desired state for a host
  • Engine - A way to run playbooks

We use Ansible to automate the configuration, deployment, and orchestration of our environments.  And after we created playbooks for Govgov, they were able to set up a new environment in an hour.

Creating an Ansible Playbook

Govgov runs various transportation applications on a three tier architecture. For part one, we’ll create an Ansible playbook to set up the web tier: an apache mod cluster load balancer.  In part two, we'll set up the JBoss nodes.

What You’ll Need

Step 1: Define Our Target Hosts

First, download and extract the starter project. This has a playbook, host file, and a load balancer configuration that we’ll use later.

Open the host file. You should see something like this:

[webservers]

An inventory (or host) file is where we define the systems we want to configure. You’ll see a group called webservers. Groups are a way to taget multiple systems at once. Ansible also allows you to target individual hosts.

Next, add a host to our group. On the line below, add:

apache ansible_connection=docker

Our first target host is called apache. We'll use a docker container because it's far quicker than you spinning up giant VMs. In a regular setup, you’d provide the IP or fully qualified hostname and ansible will work over SSH. Like this:

apache ansible_host=10.28.31.161

If you’re unfamiliar with containers, they’re a package of software and all its dependencies. It’s a really fast way to bring up & tear down environments.

Step 2: Create a Playbook

Open the playbook called site.yml. You should see this:

--- 
- name: Configure Apache Web Server 
  hosts: webservers 
  vars: apache_user: 
    apache apache_group: 
    apache 
  tasks: 
    - name: Check if HTTPD Service Exists 
      stat: path=/etc/httpd 
      register: service_status

A playbook is a list of steps to configure an entire environment. Each step, or "play", contains a series of tasks that configure a host for a purpose. Playbooks are written in yaml format with two space indents.

The first play is called Configure Apache Web Server. Here are a few things to note:

  • Hosts - sets the target host group to “webservers”
  • Vars - sets up variables that we’ll use later
  • Tasks - a list of tasks with one task

First, take a look at our one task:

- name: Check if HTTPD Service Exists 
  stat: path=/etc/httpd 
  register: service_status

A task is a single unit of action (Ex. start httpd). They have custom names and use modules to perform actions. Here, the stat module checks if /etc/httpd exists.

Then, we use the register keyword to put that status (a boolean) into a variable called service_status. The full list of ansible modules is here.

Add a second task to stop httpd if it exists:

# Be sure to line up the indents with the task above! 
# And, add a newline between each task 

- name: Ensure HTTPD service is stopped 
  when: service_status.stat.exists 
  service: 
    name: httpd 
    state: stopped

Here we use the when keyword to determine if httpd exists. If it does, the service module will stop httpd.

We’ll now create a group and user for apache. Add two tasks:

- name: Create Apache Group
  group: 
    name: "{{ apache_group }}" 
    system: yes 
    state: present 
    gid: "48" 

- name: Create Apache User
  user: 
    name: "{{ apache_user }}" 
    comment: "Apache User" 
    uid: "48" 
    group: "{{ apache_group }}" 
    state: present

These tasks ensure that a user and group is present. We're also using the variables we set up at the top to specify the user and group names. To reference a variable, we use double brackets:

{{ my var }}

Next, add a task to install httpd and a few tools:

- name: Install HTTPD & Helpful Tools 
  dnf: 
    name: httpd, unzip, wget 
    state: present

This task uses dnf ("next-gen" yum) to ensure httpd and some other packages are installed.

Now we’ll configure our load balancer, mod_cluster. Add these three tasks:

- name: Unarchive mod cluster
  unarchive: 
    src: https://github.com/modcluster/mod_cluster/releases/download/1.3.1.Final/mod_cluster-1.3.1.Final-linux2-x64-so.tar.gz 
    dest: /etc/httpd/modules 
    remote_src: yes 
    
- name: Copy Mod Cluster Config
  copy: 
    src: "mod_cluster.conf" 
    dest: "/etc/httpd/conf.d/" 
    
- name: Remove Proxy Balancer Module 
  lineinfile: 
    state: present 
    path: "/etc/httpd/conf.modules.d/00-proxy.conf" 
    regexp: "LoadModule proxy_balancer_module modules/mod_proxy_balancer.so" 
    line: "#LoadModule proxy_balancer_module modules/mod_proxy_balancer.so"

Let's break down what's going on in these tasks.

  1. The first task uses unarchive to download mod_cluster and extract them
  2. The second task copies a file from the ansible host (your machine) to the target
  3. The third task uses lineinfile to update a config file on the host
  • This line needs to be removed for mod_cluster to work

Ok. We’re ready to enable httpd and start it. Add our last two tasks:

- name: Enable HTTPD 
  service: 
    name: httpd 
    enabled: yes 
    
- name: Start HTTPD
  service: 
    name: httpd 
    state: started

Save your playbook. If all went well, our playbook should configure a base CentOS system as a load balancer.

Step 3: Run the Playbook

We’ll run our playbook on a docker container. In a terminal, start the RHEL 8 container:

docker run -dit \
--tmpfs /tmp --tmpfs /run \
-v /sys/fs/cgroup:/sys/fs/cgroup:ro \ 
-p 80:80 -p 8001:6666 -p 23364:23364/udp \ 
--name=apache registry.access.redhat.com/ubi8/ubi-init

This is mostly docker lingo. But for those interested, these parameters do a few things:

  • --tmpfs:Mount container path in host memory
  • -p:Expose containers ports  for mod_cluster (6666, 23364) and httpd (80)
  • -v: Attach a volume that's required for systemd
  • --name:Give our container a name

Open the ansible-starter directory in a terminal. And then, run our playbook:

ansible-playbook -i hosts site.yml

Here we provide the path to our inventory file (-i) and our playbook to run. You should see something like this:

Nice Work! Let’s test that our load balancer is running. Go to http://localhost and verify that you see this:

Go to http://localhost:8001/mod_cluster_manager and verify that you see this:

To clean up, stop the container:

docker rm -f apache

Best Practices

Before you create a playbook for your organization, make sure you document and test the manual steps first. That way, you can reference a known working process.

Recap

Ansible helps us automate our infrastructure setup. We defined our target hosts in an inventory file, specified our steps in a playbook, and ran ansible-playbook to configure a load balancer in minutes -- not hours.

In part two, we'll deploy our JBoss cluster and organize our playbooks with Ansible roles.

Project Code & Links

  1. Finished Ansible Project
  2. Intro to playbooks
  3. How to build your inventory

Happy Coding!

-T.O.