Skip to main content

Simplify Node Exporter Deployment with Ansible

Β· 8 min read
VoidQuark
Open-source enthusiast

Simplify Node Exporter Deployment with Ansible

In this blog post, we will explore how to leverage Ansible and the node_exporter role to streamline the deployment of Node Exporterβ€”a popular Prometheus exporter for monitoring Linux systems. By using this role, you can easily configure and deploy Node Exporter across multiple servers in your infrastructure.

Prerequisites​

Before proceeding, make sure you have Ansible installed on your control machine. Additionally, ensure that you have SSH access to the target servers and the sudo privileges for Ansible user. Please make sure that you read role README.md first!

Where are tags ?​

where_are_tags

After reading the role's README.md file, you may wonder why there are no tags mentioned for this simple role. The reason behind this choice is to keep things as straightforward as possible, eliminating the need to remember and manage various tags. While tags can be useful for more complex scenarios, such as roles with multiple tasks and configurations, this Node Exporter role focuses on simplicity. It revolves around two main scenarios: deployment and uninstallation, which can be easily achieved without the use of tags. By adopting a simpler approach, you can streamline the automation process without the added complexity of managing tags. This aligns with the goal of keeping the deployment and uninstallation of Node Exporter as straightforward as possible.

  • Deploy Playbook (function_node-exporter_deploy.yml):
- name: Deploy node_exporter service
hosts: node_exporter
gather_facts: false
become: true
roles:
- role: node_exporter
state: present
  • Uninstall Playbook (function_node-exporter_uninstall.yml):
- name: Uninstall node_exporter service
hosts: node_exporter
gather_facts: false
become: true
roles:
- role: node_exporter
state: absent

As you can see, the state parameter is set to present for deployment and absent for uninstallation.

The magic happens in the tasks/main.yml file inside the role:

- name: Deploy node_exporter service
ansible.builtin.include_tasks: deploy.yml
when: state|default('present') == 'present'

- name: Uninstall node_exporter service
ansible.builtin.include_tasks: uninstall.yml
when: state|default('present') == 'absent'

By default, the role assumes the state is present, ensuring deployment. If you remove the state: present or state: absent parameter from the playbook, it will fallback to executing the deployment, which is the expected default behavior.

This simple approach eliminates the need for additional variables in the inventory to change the state. Instead, two separate playbooks represent the desired state. This method offers clarity and ease of use, making it a preferable choice over utilizing tags for this particular use case.

Project Setup​

Create the following structure for inventory, playbooks and node_exporter role:

ansible_structure
β”œβ”€β”€ automation
β”‚ β”œβ”€β”€ function_node-exporter_deploy.yml # Deployment playbook
β”‚ β”œβ”€β”€ function_node-exporter_uninstall.yml # Uninstall playbook
β”‚ └── roles # Clone this role into this directory
β”‚ └── node_exporter
└── inventory
β”œβ”€β”€ group_vars
β”‚ └── node_exporter
β”‚ └── node_exporter_vars.yml # Overwrite variables in group_vars (optional)
β”œβ”€β”€ hosts
└── host_vars
└── node1.voidquark.com
└── host_vars.yml # Overwrite variables in host_vars (optional)

For simplicity, I will demonstrate how to use the role by cloning it using git instead of using ansible-galaxy to install it. If you are already familiar with installing roles using ansible-galaxy, feel free to use that method instead. However, I recommend using verified releases and tags when working with roles. For this demonstration, cloning the repository will suffice.

  • Follow these steps to clone the Ansible Node Exporter Role:
cd ansible_structure/automation/roles
git clone https://github.com/voidquark/node_exporter.git
  • In this example, I want to enable a few node_exporter collectors that are not enabled by default. To specify these collectors for all target systems, create or modify the following file:
vi ansible_structure/inventory/group_vars/node_exporter/node_exporter_vars.yml
node_exporter_textfile_path: "/var/lib/node_exporter"
node_exporter_runtime_flags:
- "--collector.textfile.directory {{ node_exporter_textfile_path }}"
- "--collector.systemd"
- "--collector.network_route"

Next, create the deployment and uninstall playbooks:

vi ansible_structure/automation/function_node-exporter_deploy.yml
  • Add the following content to the function_node-exporter_deploy.yml playbook:
- name: Deploy node_exporter service
hosts: node_exporter
gather_facts: false
become: true
roles:
- role: node_exporter
state: present
vi ansible_structure/automation/function_node-exporter_uninstall.yml
  • Add the following content to the function_node-exporter_uninstall.yml playbook:
- name: Uninstall node_exporter service
hosts: node_exporter
gather_facts: false
become: true
roles:
- role: node_exporter
state: absent

Make any necessary changes to the host_vars or group_vars files based on your Ansible setup. Modify the ansible.cfg file if required.

Ensure that the ansible_structure/inventory/hosts file contains the hosts you want to target. Here is an example of the content for the hosts file:

[node_exporter]
node1.voidquark.com

Deployment execution​

Now, let’s deploy Node Exporter by executing the playbook against our inventory. Open a terminal or command prompt, navigate to the directory ansible_structure and run the following command:

ansible-playbook -i inventory/hosts automation/function_node-exporter_deploy.yml

Ansible will connect to the target servers defined in the inventory, install Node Exporter, and configure it with the default settings specified in the role and also with group_vars variables to enable some defined collectors. Once the execution is complete, Node Exporter will be up and running on the target servers.

PLAY [Deploy node_exporter service] ***************************************************************

TASK [node_exporter : Deploy node_exporter service] *************************************
included: /tmp/ansible_structure/automation/roles/node_exporter/tasks/deploy.yml for node1.voidquark.com

TASK [node_exporter : Scrape Github API endpoint to obtain latest node_exporter version] ***
ok: [node1.voidquark.com -> localhost]

TASK [node_exporter : Latest available node_exporter version] ***************************
ok: [node1.voidquark.com]

TASK [node_exporter : Check if node_exporter binary is present] *************************
ok: [node1.voidquark.com]

TASK [node_exporter : Obtain current deployed node_exporter version] ********************
skipping: [node1.voidquark.com]

TASK [node_exporter : Create node_exporter system group] ********************************
changed: [node1.voidquark.com]

TASK [node_exporter : Create the node_exporter system user] *****************************
changed: [node1.voidquark.com]

TASK [node_exporter : Create textfile dir] **********************************************
changed: [node1.voidquark.com]

TASK [node_exporter : Create temp dir for node_exporter deployment] *********************
changed: [node1.voidquark.com]

TASK [node_exporter : Download node_exporter archive from remote URL] *******************
changed: [node1.voidquark.com]

TASK [node_exporter : Unarchive node_exporter binary to /tmp] ***************************
changed: [node1.voidquark.com]

TASK [node_exporter : Copy node_exporter binary from /tmp to "/usr/local/bin"] **********
changed: [node1.voidquark.com]

TASK [node_exporter : Remove temp dir] **************************************************
changed: [node1.voidquark.com]

TASK [node_exporter : Template node_exporter systemd unit file] *************************
changed: [node1.voidquark.com]

TASK [node_exporter : Enable firewalld rule to expose node_exporter port] ***************
changed: [node1.voidquark.com]

TASK [node_exporter : Ensure that node_exporter firewalld rule is not present] **********
skipping: [node1.voidquark.com]

TASK [node_exporter : Flush handlers after deployment] **********************************

RUNNING HANDLER [node_exporter : restart node_exporter] *********************************
changed: [node1.voidquark.com]

TASK [node_exporter : Ensure that node_exporter is started] *****************************
ok: [node1.voidquark.com]

TASK [node_exporter : Verify that node_exporter URL is accessible] **********************
ok: [node1.voidquark.com]

TASK [node_exporter : Uninstall node_exporter service] **********************************
skipping: [node1.voidquark.com]

PLAY RECAP ****************************************************************************************
node1.voidquark.com : ok=16 changed=11 unreachable=0 failed=0 skipped=3 rescued=0 ignored=0

Verification​

To verify the successful deployment of Node Exporter, you can use the curl command to check the metrics endpoint.

curl http://<server_ip>:9100/metrics

Replace <server_ip> with the IP address or hostname of the server where Node Exporter is deployed. Now you should see the Node Exporter metrics in the command output, indicating a successful installation.

Additionally, it's worth noting that the Node Exporter role itself ensures that the Node Exporter service is running on the target servers. It also verifies the response code 200 when accessing the metrics endpoint, providing an additional confirmation of a successful deployment.

Uninstall execution​

To uninstall Node Exporter and clean up everything created during the deployment, execute the uninstallation playbook against our inventory. Open a terminal or command prompt, navigate to the directory ansible_structure and run the following command:

ansible-playbook -i inventory/hosts automation/function_node-exporter_uninstall.yml

Ansible will connect to the target servers defined in the inventory, remove Node Exporter, and clean up any resources created during the deployment.

Consider using --limit hostname if multiple host exist in node_exporter inventory group and you want to uninstall Node Exporter from specific node.

PLAY [Uninstall node_exporter service] ************************************************************

TASK [node_exporter : Deploy node_exporter service] *************************************
skipping: [node1.voidquark.com]

TASK [node_exporter : Uninstall node_exporter service] **********************************
included: /tmp/ansible_structure/automation/roles/node_exporter/tasks/uninstall.yml for node1.voidquark.com

TASK [node_exporter : Stop node_exporter service] ***************************************
changed: [node1.voidquark.com]

TASK [node_exporter : Remove node_exporter binary and systemd unit"] ********************
changed: [node1.voidquark.com] => (item=/usr/local/bin/node_exporter)
changed: [node1.voidquark.com] => (item=/etc/systemd/system/node_exporter.service)

TASK [node_exporter : Remove node_exporter textfile dir"] *******************************
changed: [node1.voidquark.com]

TASK [node_exporter : Remove the node_exporter system user] *****************************
changed: [node1.voidquark.com]

TASK [node_exporter : Remove node_exporter system group] ********************************
ok: [node1.voidquark.com]

TASK [node_exporter : Disable firewalld port] *******************************************
changed: [node1.voidquark.com]

PLAY RECAP ****************************************************************************************
node1.voidquark.com : ok=6 changed=5 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

By utilizing Ansible and the node_exporter role, you can effortlessly deploy and uninstall Node Exporter on multiple servers, ensuring consistent configuration and clean removal when needed.

Give it a try and simplify your Node Exporter deployments and uninstallations with Ansible today!


Thanks for reading. I'm entering the void. πŸ›Έ ➑️ πŸ•³οΈ