HDP Ansible Playbook Example

In my existing collection of automated install scripts for HDP I always try to extend it with further examples of different provisioners, providers, and settings. Recently I added with hdp22-n1-centos6-ansible an example Ansible environment for preparing a HDP 2.2 installation on one node.

Ansible differs from other provisioners like Puppet or Chef by a simplified approach in dependence on SSH. It behaves almost as a distributed shell putting little dependencies on existing hosts. Where for example Puppet makes strong assumptions about the current state of a system with one or multiple nodes, does Ansible more or less reflect a collection of tasks a system gone through to reach it’s current state. While some celebrate Ansible for it’s simplicity do others abandon it for it’s lack of strong integrity.

In this post I would like to share a sample Ansible Playbook to prepare a HDP 2.2 Amabri installation using Vagrant with Virtualbox. You can download and view the in this post discussed example here.

Installing HDP w/ Ansible

Every installation of HDP with Ambari is usually quite straight forward. First all possible interfering services like iptables and selinux are disabled or removed. Talking about an Ambari installation little but the installation of an Ambari agent on all nodes together with the installation of Amabri server on one node has to be accomplished. It is probably worth mentioning that for a cluster setup it is really important networking services like DNS have to work properly between all hosts.

To install HDP you obviously also need a repository containing the required service. Part of this can also be achieved by an installation through Ambari where as we only need the Ambari repo for 1.7 here.

Summary of installation tasks:

  1. Disable/Uninstall Interfering Services
  2. Configure Networking Services
  3. Install and Configure Ambari Repository
  4. Install and Configure Ambari Agent on ALL Nodes
  5. Install, Configure, and Start Ambari Server on ONE Node
  6. Install HDP using Ambari Blueprints

Ansbile Tasks to HDP 2.2

Disable/Uninstall Interfering Services

Possible interfering service are iptables and selinux. Both are disabled with the following taks:

---
- hosts: all
  user: vagrant
  sudo: True
  tasks:
    - name: Stop iptables
      command: service iptables stop

    - name: Stop iptables6
      command: service ip6tables stop

    - name: If needed temporaly disable SELinux
      shell: echo 0 > enforce
      args:
        chdir: /selinux
        removes: enforce

    - name: Disable SElinux permanetly
      lineinfile: dest=/etc/selinux/config state=present create=no regexp='SELINUX=.*' line='SELINUX=disabled'

Configure Networking Services

Each hostname of the cluster needs to be resolve able by each host. We also need the Vagrant Host plugin, but some of this is also done with the following tasks. Also we need time synchronization using NTP:

- hosts: all
  user: vagrant
  sudo: True
  tasks:
    - name: Install NTP
      yum:
        pkg: ntp
        state: installed
    
    - name: Start NTP
      command: service ntpd start#

    - name: Create hostname entry to {{ ownhostname }}
      lineinfile: dest=/etc/hostname state=present create=yes regexp='.*' line='{{ ownhostname }}'

    - name: Set networking yes
      lineinfile: dest=/etc/sysconfig/network create=yes state=present regexp='NETWORKING=.*' line='NETWORKING=yes'

    - name: Set hostname to {{ ownhostname }}
      lineinfile: dest=/etc/sysconfig/network create=yes state=present regexp='HOSTNAME=.*' line='HOSTNAME={{ ownhostname }}'

Install and Configure Ambari Repository

We copy the Ambari repo using wget. {{ hdp_ambari_repo }} is a variable passed to the playbook. In this case the variable is set in the Vagrant file:

---
- hosts: all
  user: vagrant
  sudo: True
  tasks:

    - name: Create Ambari Repo {{ hdp_ambari_repo }}
      command: wget {{ hdp_ambari_repo }} -O /etc/yum.repos.d/ambari.repo

    - name: Clean YUM
      command: yum clean all

Install and Configure Ambari Agent on ALL Nodes

On each node we install an Ambari agent and configure the possible Amabri server hostname:

---
- hosts: all
  user: vagrant
  sudo: True
  tasks:

    - name: Install Ambari Agent
      yum:
        pkg: ambari-agent
        state: installed

    - name: Configure Ambari agent to register at Ambari server
      lineinfile: dest=/etc/ambari-agent/conf/ambari-agent.ini create=no state=present regexp='hostname=.*' line='hostname={{ ambarihostname }}'

Install, Configure, and Start Ambari Server on ONE Node

Only the “one” node installs the Amabri server. This is accomplished by the provided ansible.group config in the Vagrant file:

- hosts: ambari_host
  user: vagrant
  sudo: True
  tasks: 
    - name: Install Ambari server
      yum:
        pkg: ambari-server
        state: installed

    - name: Configure Ambari server
      command: ambari-server setup -s

    - name: Start Ambari server
      command: 'sleep 10 && ambari-server start'

Install HDP using Ambari Blueprints

As with all the given environments in the collection HDP is installed using Ambari blueprints. A default setting can be found in blueprint.json and hostmapping.json in the same folder as the Vagrant file. With ./install_blueprint.sh this can be installed.

Putting It All Together

Ansible Playbook hdp_centos6_playbook.yml:

---
- hosts: all
  user: vagrant
  sudo: True
  tasks:
    - name: Install NTP
      yum:
        pkg: ntp
        state: installed
    
    - name: Start NTP
      command: service ntpd start

    - name: Stop iptables
      command: service iptables stop

    - name: Stop iptables6
      command: service ip6tables stop

    - name: If needed temporaly disable SELinux
      shell: echo 0 > enforce
      args:
        chdir: /selinux
        removes: enforce

    - name: Disable SElinux permanetly
      lineinfile: dest=/etc/selinux/config state=present create=no regexp='SELINUX=.*' line='SELINUX=disabled'

    - name: Create hostname entry to {{ ownhostname }}
      lineinfile: dest=/etc/hostname state=present create=yes regexp='.*' line='{{ ownhostname }}'

    - name: Set networking yes
      lineinfile: dest=/etc/sysconfig/network create=yes state=present regexp='NETWORKING=.*' line='NETWORKING=yes'

    - name: Set hostname to {{ ownhostname }}
      lineinfile: dest=/etc/sysconfig/network create=yes state=present regexp='HOSTNAME=.*' line='HOSTNAME={{ ownhostname }}'

    - name: Create Ambari Repo {{ hdp_ambari_repo }}
      command: wget {{ hdp_ambari_repo }} -O /etc/yum.repos.d/ambari.repo

    - name: Clean YUM
      command: yum clean all

    - name: Install Ambari Agent
      yum:
        pkg: ambari-agent
        state: installed

    - name: Configure Ambari agent to register at Ambari server
      lineinfile: dest=/etc/ambari-agent/conf/ambari-agent.ini create=no state=present regexp='hostname=.*' line='hostname={{ ambarihostname }}'

- hosts: ambari_host
  user: vagrant
  sudo: True
  tasks: 
    - name: Install Ambari server
      yum:
        pkg: ambari-server
        state: installed

    - name: Configure Ambari server
      command: ambari-server setup -s

    - name: Start Ambari server
      command: 'sleep 10 && ambari-server start'

Vagrant file:

# -*- mode: ruby -*-
# # vi: set ft=ruby :
BOX="puppetlabs/centos-6.5-64-puppet"
BOX_URL="http://developer.nrel.gov/downloads/vagrant-boxes/CentOS-6.4-x86_64-v20130731.box"

HDP_AMBARI_REPO="http://public-repo-1.hortonworks.com/ambari/centos6/1.x/updates/1.7.0/ambari.repo"

nodes = [
    {:name => :one, :cpu => 1, :mem => 4096, :ip => "192.168.33.101"},
]

VAGRANTFILE_API_VERSION = "2"

PLAYBOOK_PATH='../../ansible'
PLAYBOOK_NAME='hdp_centos6_playbook.yml'

HOST_TLD = "hdp"
AMBARI_HOST_NAME = "one.%s" % HOST_TLD

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|

  config.vm.box = BOX
  config.vm.box_url = BOX_URL
  
  if Vagrant.has_plugin?("vagrant-cachier")
    config.cache.scope = :box
  end
  
  nodes.each do |opts|
    config.vm.define opts[:name] do |config| 
        config.vm.hostname = "%s.%s" % [opts[:name].to_s, HOST_TLD]
        config.vm.network :private_network, ip: opts[:ip]
        config.vm.provider :virtualbox do |vb|
            vb.customize ["modifyvm", :id, "--cpus", opts[:cpu] ] if opts[:cpu]
            vb.customize ["modifyvm", :id, "--memory", opts[:mem] || 2048 ]
        end

        config.vm.provision :hosts do |provisioner|
            provisioner.autoconfigure = false
            provisioner.add_localhost_hostnames = false
            nodes.each do |n|
                provisioner.add_host n[:ip], [ "%s.%s" % [ n[:name].to_s, HOST_TLD ], n[:name].to_s ]
            end
        end

        config.vm.network "forwarded_port", guest: 8080, host: 8080, auto_correct: true if "%s.%s" % [ opts[:name].to_s, HOST_TLD ] == AMBARI_HOST_NAME

        config.vm.provision "ansible" do |ansible|
           ansible.groups = {
               "ambari_host" => ['one']
           }
           ansible.extra_vars = {
               "hdp_ambari_repo" => HDP_AMBARI_REPO,
               "ownhostname" => "%s.%s" % [opts[:name].to_s, HOST_TLD],
               "ambarihostname" => AMBARI_HOST_NAME 
           }
           ansible.playbook = "%s/%s" % [PLAYBOOK_PATH, PLAYBOOK_NAME]
        end
    end
  end
end

Further Readings

  1. Automated Install with Amabri
  2. Ansible
  3. Puppet
  4. Chef
  5. Apache Ambari
  6. Vagrant Provisioning
  7. Pro Puppet: Second Edition (Amazon)
  8. Ansible: Up & Running (Amazon)

One thought on “HDP Ansible Playbook Example

Leave a comment