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 ?β
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. πΈ β‘οΈ π³οΈ