cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
722
Views
4
Helpful
0
Comments
rsilviu
Cisco Employee
Cisco Employee

This is a step by step guide of the Ansible community environment creation. We'll set up the Ansible control node, the managed nodes, and we'll deploy the Ansible role for Cisco ThousandEyes Enterprise Agent Linux package deployment on the managed nodes.

  1. Ansible terminology

    Ansible

    Ansible is an agentless automation tool that by default manages machines over the SSH protocol. Once installed, Ansible does not add a database, and there will be no daemons to start or keep running. You only need to install it on one machine (which could easily be a laptop) and it can manage an entire fleet of remote machines from that central point. When Ansible manages remote machines, it does not leave software installed or running on them.

    Ansible playbook

    Playbooks are Ansible’s configuration, deployment, and orchestration language. They can describe a policy you want your remote systems to enforce, or a set of steps in a general IT process.

    Ansible role

    Roles let you automatically load related vars, files, tasks, handlers, and other Ansible artifacts based on a known file structure. After you group your content in roles, you can easily reuse them and share them with other users.

    Control node

    Any machine with Ansible installed. You can run commands and playbooks, invoking /usr/bin/ansible or /usr/bin/ansible-playbook, from any control node. You can use any computer that has Python installed on it as a control node - laptops, shared desktops, and servers can all run Ansible. However, you cannot use a Windows machine as a control node. You can have multiple control nodes.

    Inventory

    A list of managed nodes. An inventory file is also sometimes called a “hostfile”. Your inventory can specify information like IP address for each managed node. An inventory can also organize managed nodes, creating and nesting groups for easier scaling.

    Managed nodes

    The network devices, servers, or both that you manage with Ansible. Managed nodes are also sometimes called “hosts”. Ansible is not installed on managed nodes.

  2. Set up the Ansible control node

    The control node must have network connectivity to managed nodes by SSH (TCP port 22). Ansible can be installed on multiple Operating Systems. This guide uses Ansible Community Package 8.x and 9.x installed on a machine with CentOS Stream 9. According to Ansible releases and maintenance schedule, the current version is 9.x with End of Life on May 2025, while the previous version is 8.x with End of Life on Nov 2024. We'll set up both versions on the same machine, as it will be helpful in the future to test the Ansible role's compatibility on multiple Ansible versions. The upcoming 10.x release or newer can be installed in a similar way when they'll be released.
    For any concerns related to any of the software installation and configuration on your company's infrastructure per this guide, please get advise from your Infosec or relevant departments, according to your internal policies.

    1. Install CentOS Stream 9 on your infrastructure
      There are multiple ways to install CentOS Stream 9: either on bare metal machines, or as a virtual machine (VM) within your virtual infrastructure on various hypervisors (i.e. Microsoft Hyper-V, VMWare, KVM, etc..), or your cloud infrastructure (i.e. AWS, Azure, GCP, etc..).
      My lab setup with this occasion is a VM on Hyper-V with 2 x vCPU, 2 GB RAM, 20 GB disk space, bridged network with Internet access.
      After I downloaded the latest CentoOS Stream 9 ISO image, I attached it to the VM and I went through the OS installation wizard, by configuring:
      - Date & Time
      - Software Selection: Minimal Install
      - Installation Destination: Automatic or Custom partitioning of your choice
      - Network & Host name: Manual TCP/IP configuration or DHCP, ansiblectl as hostname
      - Root Password
      - User Creation: I created user silviu part of wheel group
      After OS installation is complete, reboot and login to the VM on console or by SSH on the previously configured IP address; login as the previously created user (silviu is my username). Your prompt should look like this:
      [silviu@ansiblectl ~]$
    2. Install prerequisites packages
      II.B.1. Update the OS and reboot if necessary; use the root password when prompted and login again after reboot:
      sudo dnf update -y
      sudo reboot
      II.B.2. Install git
      sudo dnf install git -y
      II.B.3. Optional: install "nano" text editor; you may use "vi" text editor instead, which is preinstalled
      sudo dnf install nano -y
    3. Configure Virtual Environment for Ansible Community Package 8.x
      According to Ansible community changelogs table, Ansible Community Package 8.x has Core Version Dependency as 2.15. Per ansible-core support matrix table, the corresponding Control Node Python for Version 2.15 indicate Python 3.9 - 3.11. CentOS Stream 9 has Python 3.9 installed by default, which is suitable for our goal; note the downwards compatibility up to Ansible 2.10.
      II.C.1. Install Python Package Manager for Python 3
      sudo dnf install python3-pip -y
      II.C.2. Optional: check Python 3 and Python Package Manager versions (commands and sample output included)
      python3 --version
      Python 3.9.18
      
      pip3 --version
      pip 21.2.3 from /usr/lib/python3.9/site-packages/pip (python 3.9)
      II.C.3. Optional: create a separate folder where all Virtual Environments will be installed
      mkdir ~/python-env
      cd ~/python-env
      II.C.4. Create the Virtual Environment where Ansible Community Package 8.7 will be installed
      python3 -m venv ansible87
      II.C.5. Add Ansible configuration environment variables into Virtual Environment activation script.
      ANSIBLE_CONFIG is the Ansible configuration file location
      ANSIBLE_INVENTORY is the Ansible repository default file location
      ANSIBLE_DISPLAY_SKIPPED_HOSTS will prevent the skipped tasks/hosts from displaying output during playbook execution. This is a personal preference, feel free to skip this one, or add more configuration variables as needed.
      nano ansible87/bin/activate
      Insert the following lines after deactivate () {
      Sample truncated output with inserted lines:

      # This file must be used with "source bin/activate" *from bash*
      # you cannot run it directly

      deactivate () {
      unset ANSIBLE_CONFIG
      unset ANSIBLE_INVENTORY
      unset ANSIBLE_DISPLAY_SKIPPED_HOSTS
      # reset old environment variables
      ...

      Insert the following lines after export VIRTUAL_ENV

      Sample truncated output with inserted lines:

      ...
      VIRTUAL_ENV="/home/silviu/python-env/ansible87"
      export VIRTUAL_ENV
      export ANSIBLE_CONFIG=/home/silviu/python-env/ansible87/ansible.cfg

      export ANSIBLE_INVENTORY=/home/silviu/python-env/ansible87/inventory

      export ANSIBLE_DISPLAY_SKIPPED_HOSTS=false
      ...

      Exit and save the changes.
      II.C.6. Activate the ansible87 Virtual Environment
      source ansible87/bin/activate
      The prompt will change to (ansible87) [silviu@ansiblectl python-env]$, showing the virtual environment in use.
      II.C.7. Upgrade pip and setuptools
      pip3 install --upgrade pip setuptools
      Output should end in Successfully installed pip-23.3.1 setuptools-69.0.2 (your versions might be newer).
      II.C.8. Optional: check available Ansible Community Package versions
      pip3 index versions ansible
      Sample truncated output (you may ignore the warning for now):
      WARNING: pip index is currently an experimental command. It may be removed/changed in a future release without prior warning.
      ansible (8.7.0)
      Available versions: 8.7.0, 8.6.1, 8.6.0, ...
      II.C.9 Install the Ansible version 8.7.
      As this is the last version, the following command may be run without specifying the trailing version and the result would be the same. If a different version was needed, the version should be specified (i.e. ==8.7)
      pip3 install ansible==8.7
      II.C.10. Optional: check the installed packages
      pip3 list
      Sample output:
      Package
      -------------------
      ansible
      ansible-core
      cffi
      cryptography
      importlib-resources
      Jinja2
      MarkupSafe
      packaging
      pip
      pycparser
      PyYAML
      resolvelib
      setuptools
      Version
      -------
      8.7.0
      2.15.8
      1.16.0
      41.0.7
       5.0.7
      3.1.2
      2.1.3
      23.2
      23.3.1
      2.21
      6.0.1
      1.0.1
      69.0.2
      II.C.11. Create Ansible configuration file with all settings disabled to defaults
      ansible-config init --disabled -t all > ansible87/ansible.cfg
      II.C.12. Edit Ansible configuration file
      The environment variables that we set in II.C.5 section above takes precedence over the same settings within ansible.cfg file.
      nano ansible87/ansible.cfg
      Various approaches can be taken while amending the ansible.cfg file. I usually search for the setting that I'd like to change (i.e. CTRL+W, type roles_path=, then press Enter) and add the new line immediately after the corresponding commented line (the lines in bold were added).
      My favorite settings for my lab are:

      ...
      # (pathspec) Colon separated paths in which Ansible will search for Roles.
      ;roles_path={{ ANSIBLE_HOME ~ "/roles:/usr/share/ansible/roles:/etc/ansible/roles" }}

      roles_path=/home/silviu/python-env/ansible87/roles

      ...
      ;inventory=/etc/ansible/hosts

      inventory=/home/silviu/python-env/ansible87/inventory

      ...

      # (boolean) Toggle to control displaying skipped task/host entries in a task in the default callback
      ;display_skipped_hosts=True

      display_skipped_hosts=False

      ...

      # (string) Path to the Python interpreter to be used for module execution on remote targets, or an automatic discovery mode. Supported discovery>
      ;interpreter_python=auto

      interpreter_python=auto_silent

      ...

      # (boolean) Set this to "False" if you want to avoid host key checking by the underlying tools Ansible uses to connect to the host
      ;host_key_checking=True

      host_key_checking=False   ;there are multiple occurrences of this line

      ...

      # (list) List of enabled callbacks, not all callbacks need enabling, but many of those shipped with Ansible do as we don't want them activated by default
      ;callbacks_enabled=

      callbacks_enabled=ansible.posix.timer

      ...

      # (boolean) If you have cowsay installed but want to avoid the 'cows' (why????), use this.
      ;nocows=False

      nocows=True


      Spoiler
      You noticed that setting display_skipped_hosts=False in ansible.cfg is redundant, as ANSIBLE_DISPLAY_SKIPPED_HOSTS=false environment variable is set. However host_key_checking=False in ansible.cfg, which doesn't have an environment variable set, will add up to the overall configuration. Feel free to use environment variables, ansible.cfg settings or combination of both, observing the precedence.
      Spoiler
      Before amending any of the above Ansible Configuration Settings, take a moment and make yourself familiar to what they actually do.
      Exit and save the changes.
      II.C.13. Create the inventory file
      nano ansible87/inventory
      Add the lines which corresponds to the IP addresses of the managed nodes grouped under [allagents], on which we'll deploy the ThousandEyes Enterprise Agent Linux package software through the Ansible role:
      [allagents]
      192.168.8.235
      192.168.8.238
      Exit and save the changes.
      II.C.14. Deactivate the Virtual Environment for Ansible Community Package 8.7
      deactivate
      The prompt will change back to [silviu@ansiblectl python-env]$
    4. Configure Virtual Environment for Ansible Community Package 9.x
      According to Ansible community changelogs table, Ansible Community Package 9.x has Core Version Dependency as 2.16. Per ansible-core support matrix table, the corresponding Control Node Python for Version 2.16 indicate Python 3.10 - 3.12. CentOS Stream 9 has Python 3.9 installed by default, therefore we'll proceed by installing Python 3.11.
      Spoiler
      - Hey, can't I just use Python 3.11 for both Virtual Environments for Ansible Community Package 8.x, respectively 9.x?
      - Yes, you can also do that! However, if you'd like to use older versions of Ansible 3.x to 6.x, Python 3.9 is the way to go, while Ansible 7.x and 8.x can use both Python 3.9 and Python 3.11.
      II.D.1. Install Python 3.11
      sudo dnf install python3.11 python3.11-pip
      II.D.2. Optional: check Python 3.11 and Python Package Manager versions (commands and sample output included)
      python3.11 --version
      Python 3.11.5
      
      pip3.11 --version
      pip 22.3.1 from /usr/lib/python3.11/site-packages/pip (python 3.11)

      II.D.3. Create the Virtual Environment where Ansible Community Package 9.1 will be installed

      python3.11 -m venv ansible91
      II.D.4. Add Ansible configuration environment variables into Virtual Environment activation script.
      ANSIBLE_CONFIG is the Ansible configuration file location
      ANSIBLE_INVENTORY is the Ansible repository default file location
      ANSIBLE_DISPLAY_SKIPPED_HOSTS will prevent the skipped tasks/hosts from displaying output during playbook execution. This is a personal preference, feel free to skip this one or add more configuration variables as needed.
      nano ansible91/bin/activate
      Insert the following lines after deactivate () {
      Sample truncated output with inserted lines:

      # This file must be used with "source bin/activate" *from bash*
      # you cannot run it directly

      deactivate () {
      unset ANSIBLE_CONFIG
      unset ANSIBLE_INVENTORY
      unset ANSIBLE_DISPLAY_SKIPPED_HOSTS
      # reset old environment variables
      ...

      Insert the following lines after export VIRTUAL_ENV

      Sample truncated output with inserted lines:

      ...
      VIRTUAL_ENV="/home/silviu/python-env/ansible87"
      export VIRTUAL_ENV
      export ANSIBLE_CONFIG=/home/silviu/python-env/ansible87/ansible.cfg

      export ANSIBLE_INVENTORY=/home/silviu/python-env/ansible87/inventory

      export ANSIBLE_DISPLAY_SKIPPED_HOSTS=false
      ...

      Exit and save the changes.
      II.D.5. Activate the ansible91 Virtual Environment
      source ansible91/bin/activate
      The prompt will change to (ansible91) [silviu@ansiblectl python-env]$, showing the virtual environment in use.
      II.D.6. Upgrade pip and setuptools
      pip3.11 install --upgrade pip setuptools
      Output should end in Successfully installed pip-23.3.1 setuptools-69.0.2 (your versions might be newer).
      II.D.7. Optional: check available Ansible Community Package versions
      pip3.11 index versions ansible
      Sample truncated output (you may ignore the warning for now):
      WARNING: pip index is currently an experimental command. It may be removed/changed in a future release without prior warning.
      ansible (9.1.0)
      Available versions: 9.1.0, 9.0.1, 8.7.0, ...
      II.D.8. Install the Ansible version 9.1. As this is the last version, the following command may be run without specifying the trailing version and the result would be the same. If a different version was needed, the version should be specified (i.e. ==9.1)
      pip3.11 install ansible==9.1
      II.D.9. Optional: check the installed packages
      pip3.11 list
      Sample output:
      Package
      -------------------
      ansible
      ansible-core
      cffi
      cryptography
      Jinja2
      MarkupSafe
      packaging
      pip
      pycparser
      PyYAML
      resolvelib
      setuptools
      Version
      -------
      9.1.0
      2.16.2
      1.16.0
      41.0.7
      3.1.2
      2.1.3
      23.2
      23.3.1
      2.21
      6.0.1
      1.0.1
      69.0.2
      II.D.10. Create Ansible configuration file with all settings disabled to defaults
      ansible-config init --disabled -t all > ansible91/ansible.cfg
      II.D.11. Edit Ansible configuration file
      The environment variables that we set in II.D.4 section above takes precedence over the same settings within ansible.cfg file.
      nano ansible91/ansible.cfg
      Various approaches can be taken while amending the ansible.cfg file. I usually search for the setting that I'd like to change (i.e. CTRL+W, type roles_path=, then press Enter) and add the new line immediately after the corresponding commented line (the lines in bold were added).
      My favorite settings for my lab are:

      ...
      # (pathspec) Colon separated paths in which Ansible will search for Roles.
      ;roles_path={{ ANSIBLE_HOME ~ "/roles:/usr/share/ansible/roles:/etc/ansible/roles" }}

      roles_path=/home/silviu/python-env/ansible91/roles

      ...
      ;inventory=/etc/ansible/hosts

      inventory=/home/silviu/python-env/ansible91/inventory

      ...

      # (boolean) Toggle to control displaying skipped task/host entries in a task in the default callback
      ;display_skipped_hosts=True

      display_skipped_hosts=False

      ...

      # (string) Path to the Python interpreter to be used for module execution on remote targets, or an automatic discovery mode. Supported discovery>
      ;interpreter_python=auto

      interpreter_python=auto_silent

      ...

      # (boolean) Set this to "False" if you want to avoid host key checking by the underlying tools Ansible uses to connect to the host
      ;host_key_checking=True

      host_key_checking=False   ;there are multiple occurrences of this line

      ...

      # (list) List of enabled callbacks, not all callbacks need enabling, but many of those shipped with Ansible do as we don't want them activated by default
      ;callbacks_enabled=

      callbacks_enabled=ansible.posix.timer

      ...

      # (boolean) If you have cowsay installed but want to avoid the 'cows' (why????), use this.
      ;nocows=False

      nocows=True

      Exit and save the changes.
      II.D.12. Create the inventory file
      nano ansible91/inventory
      Add the lines which corresponds to the IP addresses of the managed nodes grouped under [allagents], on which we'll deploy the ThousandEyes Enterprise Agent Linux package software through the Ansible role:
      [allagents]
      192.168.8.235
      192.168.8.238
      Exit and save the changes.
      II.D.13. Deactivate the Virtual Environment for Ansible Community Package 9.1
      deactivate​
      The prompt will change back to [silviu@ansiblectl python-env]$
  3. Set up the Ansible managed node(s)

    The managed nodes are Linux machines installed with a supported OS per Requirements section which is aligned with Enterprise Agent Support Lifecycle Knowledge Base article. There are multiple ways to install the managed nodes: either on bare metal machines, or as a virtual machine (VM) within your virtual infrastructure on various hypervisors (i.e. Microsoft Hyper-V, VMWare, KVM, etc..), or your cloud infrastructure (i.e. AWS, Azure, GCP, etc..).
    I set up two managed nodes within my lab setup (you may set up as many managed nodes you need set up as ThousandEyes Enterprise Agents). These two VMs resides on Hyper-V with 2 x vCPU, 2 GB RAM, 20 GB disk space, bridged network with Internet access, per hardware requirements.
    After I downloaded the latest CentOS-7-x86_64-Minimal-2009.iso and Ubuntu Server 20.04 LTS, I created two VMs attaching the coresponding ISO image to the VM and I went through the OS installation wizard for each VM, by configuring:
    - Date & Time
    It's important to configure time sync with a reliable time server within your network or on the Internet.
    - Software Selection: Minimal Install
    - Installation Destination: Automatic or Custom partitioning of your choice (i.e. 1 GB boot partition, large root partition, small swap partition)
    - Network & Host name: Manual TCP/IP configuration or DHCP, ea-linux-1, respectively ea-linux-2 as hostname
    Observe the IP addresses and adjust accordingly in inventory files in II.C.13. and II.D.12. sections above.
    - Root Password
    - User Creation: I created the ansible user, part of wheel group
    - Tick SSH service installation on Ubuntu
    After OS installation is complete, reboot. My managed nodes ea-linux-1, respectively ea-linux-2 with IP addresses 192.168.8.235, respectively 192.168.8.238 are now ready for the next step.
  4. Deploy the Ansible role for Cisco ThousandEyes Enterprise Agent Linux package on managed nodes

    1. Deploy with Ansible 8.7
      IV.A.1 Activate the Vitual Environment
      source ansible87/bin/activate
      IV.A.2 Clone the ansible-role-thousandeyes-enterprise-agent-linux repository into the Ansible roles folder location
      mkdir ansible87/roles
      git clone https://github.com/cisco-open/ansible-role-thousandeyes-enterprise-agent-linux.git ansible87/roles/ansible-role-thousandeyes-enterprise-agent-linux
      IV.A.3 Create Ansible playbook
      nano ansible87/install_thousandeyes.yml
      Sample content with correct space indentation:
      ---
      - hosts: allagents
        remote_user: ansible
        gather_facts: no
      # Uncommenting this line allows each host to run until the end of the play as fast as it can
      # strategy: free
        pre_tasks:
          - setup:
              gather_subset:
                - '!all'
                - '!any'
                - hardware
                - virtual
        become: true
        roles:
      #    - common
      #    - rhel-system-roles.timesync
          - ansible-role-thousandeyes-enterprise-agent-linux
      #    - other-roles
      Exit and save the file.
      IV.A.4 Configure Ansible role variables
      Review and set various role variables in vars/main.yml. The Account Group token variable is mandatory and it will determine in which Account Group your ThousandEyes Enterprise Agent will be installed. The rest of the variables are set to defaults.
      nano ansible87/roles/ansible-role-thousandeyes-enterprise-agent-linux/vars/main.yml
      Sample configuration:

      ---
      # Copyright (c) 2023 Cisco Systems, Inc. and its affiliates
      # All rights reserved..

      # vars file

      # Account Group in which the Enterprise Agent will be installed
      # Where can I get the Account Group Token?
      # https://docs.thousandeyes.com/product-documentation/enterprise-agents/where-can-i-get-the-account-group-token
      ACCOUNT_TOKEN: "32charstoken12345678901234567890"
      ...
      SKIP_DESKTOP_CHECK: "yes"
      ...

      IV.A.5 Run the playbook
      The remote user is ansible, as defined within the playbook; see section IV.A.3 above.
      The -k and -K parameters will interactively ask for remote user's password and the remote root's password. The -k parameter can be avoided by setting up key-based authentication for SSH. The -K parameter can be avoided by adding the ansible remote user to sudoers, or by setting the ansible_become_password connection variable. From a security standpoint, passwords should never be stored in plain text. For information on encrypting your passwords and other secrets, see Ansible Vault.
      sudo dnf install sshpass -y
      ansible-playbook -k -K ansible87/install_thousandeyes.yml
      After the playbook finish running, the output of each task is displayed (except skipped tasks as configured above), with PLAY RECAP at the end, and total time took to run the playbook - provided by the configured ansible.posix.timer callback.
      Sample output:
      SSH password:
      BECOME password[defaults to SSH password]:
      PLAY [allagents] *****************
      TASK [setup] *****************
      ok: [192.168.8.235]
      ok: [192.168.8.238]
      TASK [ansible-role-thousandeyes-enterprise-agent-linux : ====================Welcome to ThousandEyes====================] **
      ...
      TASK [ansible-role-thousandeyes-enterprise-agent-linux : Starting ThousandEyes BrowserBot] *****************
      ok: [192.168.8.235]
      ok: [192.168.8.238]

      TASK [ansible-role-thousandeyes-enterprise-agent-linux : Starting the ThousandEyes Agent] *****************
      changed: [192.168.8.238]
      changed: [192.168.8.235]

      PLAY RECAP *****************
      192.168.8.235 : ok=24 changed=10 unreachable=0 failed=0 skipped=46 rescued=0 ignored=0
      Playbook run took 0 days, 0 hours, 0 minutes, 19 seconds
      192.168.8.238 : ok=24 changed=10 unreachable=0 failed=0 skipped=37 rescued=0 ignored=0
      Playbook run took 0 days, 0 hours, 4 minutes, 58 seconds
      Your ThousandEyes Enterprise Agents (Linux package) should now be found within your ThousandEyes portal and ready to be assigned tests.
      IV.A.6 Deactivate the Virtual Environment
      deactivate
    2. Deploy with Ansible 9.1
      Follow the steps from IV.A.1 to IV.A.6 and replace ansible87 with ansible91 everywhere.
  5. Delete unused Ansible versions

    Once you determined that all your Ansible playbooks are working as expected with your intended Ansible versions, or maybe you won't use any end of life Ansible versions any more, you may delete that version simply by removing the Virtual Environment folder, i.e.
    rm -rfv ansible87



Dear Community member, thank you for reading the article! if you find this article useful, click on the thumbs up button!
Would you like to see more ThousandEyes automation related articles? Feel free to leave comments below and share your automation experience with the rest of the Community.

 

Getting Started

Find answers to your questions by entering keywords or phrases in the Search bar above. New here? Use these resources to familiarize yourself with the community: