Ansible is a powerhouse of configuration management and can power a lot of automation but add Tower to that and you add so much more.  Using Ansible Tower you get Role Based Access Control (RBAC), push button automation, centralized logging and a host of other features.

Tower, like Ansible is owned by Red Hat, and has a pay for support version.  However, also like Ansible there is an upstream opensource version of Tower called AWX.  AWX does everything the RHEL supported version of Tower does except integrate with the new RHEL cloud.redhat.com insight analytics.  Unlike Tower though, AWX can be simply installed in a Docker deployment.  That is what I am going to cover here.

There are plenty of guides out there for installing Docker on Linux, Windows, and Apple so I am not going to cover that.  Just make sure in addition to the Docker engine you also have the docker-compose binary installed.  You also need to have Ansible installed on the host.  I suggest using a Linux host to make this as easy as possible.

On the host where you have Docker running you will need to clone the AWX git repo

$ git clone https://github.com/ansible/awx.git

Cd into the awx installer directory

$ cd awx/installer

The installer is an Ansible play that will do all the work of creating the docker-compose file as well as some environmental links.  Take a look at the inventory file and update any passwords you would like to change. You can leave everything commented that already is, as this install is for Docker, not Kubernetes or the RHEL supported Kubernetes version, OpenShift.

Once you have the passwords the way you want them, run the AWX install playbook.

$ ansible-playbook -i inventory install.yml 

This will create the directory /tmp/awxcompose, populate that directory with a docker-compose file, and some environment files.  Also, a directory /tmp/pgdocker will be created for the Postgres database.  The playbook will also run the docker-compose file to stand up the Tower docker environment.

AWX Tower has placed all its files in the home directory of the user who ran the install.yml playbook.  You can find these files at ‘~/.awx

Once the stack is started, you can connect to the container that handles the ansible tasks called awx_task

There are a few changes that need to be made to one of the containers to bring the running version of Ansible Engine up to the current and to assure that you not only have the latest NetApp modules, but also the libraries to use them.

$ docker exec -it awx_task bash

After connecting we will install some packages so that NetApp modules will work.  The AWX Tower install of Ansible is version locked at 2.8.5 which is old.  These steps will also remove that version, add the current version, and set up the necessary links so everything still works.

bash-4.4# pip3 install netapp-lib requests solidfire-sdk-python
bash-4.4# yum remove ansible
bash-4.4# pip3 install ansible
bash-4.4# ln -s /usr/local/bin/ansible /usr/bin/ansible
bash-4.4# ln -s /usr/local/bin/ansible-galaxy /usr/bin/ansible-galaxy
bash-4.4# ln -s /usr/local/bin/ansible-doc /usr/bin/ansible-doc
bash-4.4# ansible-galaxy collection install netapp.ontap -p /usr/share/ansible/collections
bash-4.4# ansible-galaxy collection install netapp.elementsw -p /usr/share/ansible/collections

You can also install any additional collections you want to use at this point using the appropriate namespace and collection you want (i.e., netapp.aws, cisco.ios, etc).

*When Ansible or the Collections need to be updated repeat the ‘docker exec’ command and the last three lines of the above commands to upgrade.

Log out of the container

bash-4.4# exit

Tower is now running on the host at port 80.  The rest of the setup is handled by the web interface .  If you did this on the system you are using you can use http://localhost

If you wish to move where the AWX Tower files are kept for any reason this can easily be accomplished.  The first thing to do is to stop the running AWX Tower stack.

$ cd ~/.awx/awxcompose
$ docker-compose stop 

This will stop and remove the created Docker containers so that after modifications they will be created the way they are needed for the new location.  Next, the new location needs to be created.  In this example, I will be creating a directory called /awx_tower.  Once you have the permanent directory, the existing directories need to be moved to that location.

$ mkdir /awx_tower
$ mv ~/.awx/* /awx_tower/

With the directories moved, now the compose file needs to be edited to point at the new location.

 $ cd /awx_tower/awxcompose

Now edit the docker-compose.yml file so it reads like this.

version: '2'
services: 
  web:
    image: ansible/awx_web:9.0.1
    container_name: awx_web
    depends_on:
      - rabbitmq
      - memcached
      - postgres
    ports:
      - "80:8052"
    hostname: awxweb
    user: root
    restart: unless-stopped
    volumes:
      - "/awx_tower/awxcompose/SECRET_KEY:/etc/tower/SECRET_KEY"
      - "/awx_tower/awxcompose/environment.sh:/etc/tower/conf.d/environment.sh"
      - "/awx_tower/awxcompose/credentials.py:/etc/tower/conf.d/credentials.py"
      - "/awx_tower/awxcompose/nginx.conf:/etc/nginx/nginx.conf:ro"
    environment:
      http_proxy:
      https_proxy:
      no_proxy:

   task:
    image: ansible/awx_task:9.0.1
    container_name: awx_task
    depends_on:
      - rabbitmq
      - memcached
      - web
      - postgres
    hostname: awx
    user: root
    restart: unless-stopped
    volumes:
      - "/awx_tower/awxcompose/SECRET_KEY:/etc/tower/SECRET_KEY"
      - "/awx_tower/awxcompose/environment.sh:/etc/tower/conf.d/environment.sh"
      - "/awx_tower/awxcompose/credentials.py:/etc/tower/conf.d/credentials.py"
    environment:
      http_proxy:
      https_proxy:
      no_proxy:

   rabbitmq:
    image: ansible/awx_rabbitmq:3.7.4
    container_name: awx_rabbitmq
    restart: unless-stopped
    environment:
      RABBITMQ_DEFAULT_VHOST: "awx"
      RABBITMQ_DEFAULT_USER: "guest"
      RABBITMQ_DEFAULT_PASS: "awxpass"
      RABBITMQ_ERLANG_COOKIE: cookiemonster
      http_proxy:
      https_proxy:
      no_proxy:

   memcached:
    image: "memcached:alpine"
    container_name: awx_memcached
    restart: unless-stopped
    environment:
      http_proxy:
      https_proxy:
      no_proxy:

   postgres:
    image: postgres:10
    container_name: awx_postgres
    restart: unless-stopped
    volumes:
      - /awx_tower/pgdocker/10/data/:/var/lib/postgresql/data/pgdata:Z
    environment:
      POSTGRES_USER: awx
      POSTGRES_PASSWORD: awxpass
      POSTGRES_DB: awx
      PGDATA: /var/lib/postgresql/data/pgdata
      http_proxy:
      https_proxy:
      no_proxy:

The highlighted parts are the most important bits to be sure are correct.  Now all that’s left is to redeploy the stack and re-do the updates from when you first installed AWX Tower (the pip upgrades and NetApp installs).  To restart your stack so that you can do the updates on this newly deployed container run the up docker-compose command

$ docker-compose up -d

If you ever need to stop the stack, just change to the directory and run the docker stop command.  Running the stop command instead of the down command will save your containers so you don’t have to do the manual updates every time.

$ cd /awx_tower/awxcompose
$ docker-compose stop

Happy towering.  Check back at netapp.io later for more posts on Ansible and Tower, as well as information about containers, and OpenStack.  As always, any questions you have can be asked in our Slack workspace.  Get your invite at netapp.io/slack and join me in the #configurationmgmt channel.

David Blackwell on Linkedin
David Blackwell
Technical Marketing Engineer at NetApp
David is a twenty year IT veteran who has been an admin for just about every aspect of a DataCenter at one time or another. When not working, or tinkering with new software at home, David spends most of his free with his four year old son and his lovely wife.

Pin It on Pinterest