Skip to content

Lab 6 - Infrastructure AutomationπŸ”—

Lab 6.1 Configure the NAT Network
Lab 6.2 Set up GitHub Repository
Lab 6.3 Install the CSR1000v VM
Lab 6.4 Use Ansible to Back Up and Configure a Device
Lab 6.5 Use Ansible to Automate Installing a Web Server

6.1 Configure the NAT NetworkπŸ”—

ObjectivesπŸ”—

    Part 1: Create the NAT Network
    Part 2: Configure the DEVASC VM to use the NAT Network

InstructionsπŸ”—

Part 1: Create the NAT NetworkπŸ”—

Important

If you properly completed Part 1, Step 2 of the first lab (Lab 1 - Dev Environment) then it's likely this NAT network is already configured. Simply verify the settings match the outputs below, but don't change anything if they are already set correctly from Lab 1.

  1. Press Ctrl+H, or click the Network icon on the left (see the screenshot), or click File > Tools > Network

    Screenshot showing the location of the VirtualBox Tools Button

  2. Click on the NAT Networks tab

  3. If you already see a NAT Network called DEVASC with the IPv4 Prefix 10.0.2.0/24 then you already have the NAT Network and can skip to Part 2. Otherwise, click the Create button at the top of the window.

    Screenshot showing where the NAT Network tab is in VirtualBox

  4. In the Name box at the bottom of the screen type DEVASC. In the IPv4 Prefix box type 10.0.2.0/24. Ensure that the Enable DHCP checkbox is checked. You do not need to check the Enable IPv6 checkbox. Click the Apply button to apply the settings.

    Screenshot showing where to select Enable DHCP in the VirtualBox settings

Part 2: Configure the DEVASC VM to use the NAT NetworkπŸ”—

  1. Return to the list of virtual machines, click on the DEVASC-LABVM virtual machine, then click the Settings button

    Screenshot of accessing the settings of the DEVASC-LABVM virtual machine

  2. In the settings window, click on Network in the left navigation pane. On the Adapter 1 tab, change the Attached to: dropdown to NAT Network and ensure the Name field says DEVASC. Click OK to close the settings.

    Screenshot showing the network adapter settings for the DEVASC VM

6.2 Set up GitHub RepositoryπŸ”—

ObjectivesπŸ”—

    Part 1: Join the GitHub Classroom
    Part 2: Initialize the Local Repository
    Part 3: Set up the Remote Repository

InstructionsπŸ”—

Part 1: Join the GitHub ClassroomπŸ”—

  1. Follow the GitHub assignment link posted in Canvas. If you did not complete the setup in Lab 2.2 you will need to authorize GitHub Classroom to link with your account and select your name from the list of students.

  2. Accept the assignment and refresh the page until it says your repository has been created. Click the link to proceed to the repository.

    Important

    GitHub Classroom is currently experiencing a bug where you might receive a Repository Access Issue error after accepting the assignment. If this happens, check the e-mail connected to your GitHub account for an invitation e-mail from GitHub. Use the View Invitation link in the e-mail to see the link to accept the invitation and proceed to the repository.

  3. Select the Code dropdown and copy the HTTPS URL. Store it somewhere for use in a later step.

    Tip

    If you've configured your VM to use SSH to connect to GitHub instead of HTTPS, click on the Code dropdown, select the SSH tab, and copy the URL from there instead.

Part 2: Initialize the Local RepositoryπŸ”—

You will be creating a local repository from a folder on the DEVASC VM. This folder already contains some files, so you will need to initialize a repository in the folder, pull down the files from the remote GitHub Classroom repository, then add the local files to the local repository to combine the remote and local files into a single repository.

  1. Inside the DEVASC VM, open a terminal and change to the ~/labs/devnet-src/ansible directory.

    devasc@labvm:~$ cd labs/devnet-src/ansible/
    devasc@labvm:~/labs/devnet-src/ansible$
    
  2. View the listing of the files and folders currently in the ansible directory.

    devasc@labvm:~/labs/devnet-src/ansible$ ls -la
    total 16
    drwxr-xr-x 4 devasc devasc 4096 Jun 1 2020 .
    drwxr-xr-x 17 devasc devasc 4096 Mar 8 21:57 ..
    drwxr-xr-x 2 devasc devasc 4096 Jun 2 2020 ansible-apache
    drwxr-xr-x 2 devasc devasc 4096 Jun 2 2020 ansible-csr1000v
    devasc@labvm:~/labs/devnet-src/ansible$
    
  3. Initialize this directory as a Git repository (don’t miss the . at the end of the command).

    devasc@labvm:~/labs/devnet-src/ansible$ git init .
    Initialized empty Git repository in /home/devasc/labs/devnet-src/ansible/.git/
    devasc@labvm:~/labs/devnet-src/ansible$
    

Part 3: Set up the Remote RepositoryπŸ”—

  1. Since we initialized our own local repository, rather than cloning an existing remote repository, we need to tell Git the location of the remote repository to synchronize with. Configure the location of the remote repository using the git remote add command. Use the URL to the GitHub Classroom repository you copied at the end of Part 1, not the one in the command below.

    Tip

    If you've configured your VM to use SSH to connect to GitHub, use the SSH URL that you copied in step 1, rather than the HTTPS link.

    devasc@labvm:~/labs/devnet-src/ansible$ git remote add origin https://github.com/Ontario-Tech-NITS/lab-6-infrastructure-automation-<username>.git
    devasc@labvm:~/labs/devnet-src/ansible$
    

    Important

    Make sure you use your GitHub URL that you copied in Part 1, not the one in the command example! Also, if you're using SSH, your URL will start with git@github.com rather than https://.

  2. Verify that the remote is properly configured with the git remote --verbose command.

    devasc@labvm:~/labs/devnet-src/ansible$ git remote --verbose
    origin https://github.com/Ontario-Tech-NITS/lab-6-infrastructure-automation-<username>.git (fetch)
    origin https://github.com/Ontario-Tech-NITS/lab-6-infrastructure-automation-<username>.git (push)
    devasc@labvm:~/labs/devnet-src/ansible$
    
  3. Pull down the files from the remote repository into the local repository. Remember to use your Personal Access Token as the password.

    Tip

    If you've configured your VM to use SSH to connect to GitHub instead of HTTPS, you will not be asked for a username and password, although you may be asked for a passphrase for your SSH key, if you configured one.

    devasc@labvm:~/labs/devnet-src/ansible$ git pull origin main
    Username for 'https://github.com': username
    Password for 'https://username@github.com': Personal Access Token
    remote: Enumerating objects: 16, done.
    remote: Counting objects: 100% (16/16), done.
    remote: Compressing objects: 100% (11/11), done.
    remote: Total 16 (delta 1), reused 6 (delta 0), pack-reused 0 (from 0)
    Unpacking objects: 100% (16/16), 5.73 KiB | 2.87 MiB/s, done.
    From github.com:Ontario-Tech-NITS/lab-6-infrastructure-automation-josh-test-student
     * branch            main       -> FETCH_HEAD
     * [new branch]      main       -> origin/main
    devasc@labvm: :~/labs/devnet-src/ansible$
    
  4. Use git status to verify all the local files and folders are currently untracked.

    devasc@labvm:~/labs/devnet-src/ansible$ git status
    On branch main
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
            ansible-apache/
            ansible-csr1000v/
    
    nothing added to commit but untracked files present (use "git add" to track)
    devasc@labvm:~/labs/devnet-src/ansible$
    
  5. Add the files from the local working folder to the staging area (don’t miss the . at the end of the command).

    devasc@labvm:~/labs/devnet-src/ansible$ git add .
    devasc@labvm:~/labs/devnet-src/ansible$
    
  6. Commit these new files to the local repository. Use the commit message Initializing the repository.

    devasc@labvm:~/labs/devnet-src/ansible$ git commit -m "Initializing the repository"
    [main d37a4d7] Initializing the repository
     8 files changed, 4 insertions(+)
     create mode 100644 ansible-apache/ansible.cfg
     create mode 100644 ansible-apache/checklocalinfo.yml
     create mode 100644 ansible-apache/hosts
     create mode 100644 ansible-apache/servers
     create mode 100644 ansible-csr1000v/ansible.cfg
     create mode 100644 ansible-csr1000v/checklocalinfo.yml
     create mode 100644 ansible-csr1000v/hosts
     create mode 100644 ansible-csr1000v/servers
    devasc@labvm:~/labs/devnet-src/ansible$
    
  7. Use git status again to verify that all files have been committed to the local repository and that you are working on a clean tree.

    devasc@labvm:~/labs/devnet-src/ansible$ git status
    On branch main
    nothing to commit, working tree clean
    devasc@labvm:~/labs/devnet-src/ansible$
    
  8. Push the local repository to the remote repository on GitHub, adding the files from the DEVASC VM to the existing repository. Remember to use your Personal Access Token when prompted for your password.

    Tip

    If you've configured your VM to use SSH to connect to GitHub instead of HTTPS, you will not be asked for a username and password, although you may be asked for a passphrase for your SSH key, if you configured one.

    devasc@labvm:~/labs/devnet-src/ansible$ git push origin main
    Username for 'https://github.com': username
    Password for 'https://username@github.com': Personal Access Token
    Enumerating objects: 7, done.
    Counting objects: 100% (7/7), done.
    Delta compression using up to 2 threads
    Compressing objects: 100% (4/4), done.
    Writing objects: 100% (6/6), 617 bytes | 617.00 KiB/s, done.
    Total 6 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
    To github.com:Ontario-Tech-NITS/lab-6-infrastructure-automation-<username>.git
       3d55449..d37a4d7 main -> main
    devasc@labvm:~/labs/devnet-src/ansible$
    
  9. Using a web browser, open the remote repository on GitHub and verify that you see the newly tracked files and folders. Your local and remote repositories are now synchronized, and you are ready to complete the rest of the lab, committing your changes as you go (when instructed).

    Screenshot of GitHub Repository at the end of Lab 6.2

6.3 Install the CSR1000v VMπŸ”—

ObjectivesπŸ”—

    Part 1: Install the CSR1000v VM on VirtualBox
    Part 2: Verify Communications to CSR1000v VM

BackgroundπŸ”—

In this lab, you will install the CSR1000v Cloud Services Router. This is a Cisco software virtual router deployed on a virtual machine (VM) instance on x86 server hardware. When the Cisco CSR 1000v is deployed on a VM, the Cisco IOS XE software functions exactly the same as if it were deployed on a traditional Cisco hardware platform. You can configure different features depending on the Cisco IOS XE software image.

Note

The CSR1000v name will be shortened to CSR1kv in future labs. However, for this lab we use CSR1000v.

InstructionsπŸ”—

Part 1: Install the CSR1000v VM on VirtualBoxπŸ”—

Install the CSR1000v VM directly on your x86 computer. It requires at least 4GB of RAM.

Step 1: Download the CSR1000v ISO fileπŸ”—

Important

Only the instructor is able to download ISO files from Cisco. The CSR1000v ISO has been downloaded and shared on Canvas for your use only in this class.

Cisco does not make this software publicly available for free, and you are only allowed to use the software as part of this course.

  1. Download the CSR1kv ISO file from the Labs module on Canvas. This will require you to use your @ontariotechu.net e-mail account. Note the location of the downloaded image on your computer.

Step 2: Download the CSR1000v VM OVA fileπŸ”—

  1. Download the CSV1kv VirtualBox OVA file from the Labs module on Canvas. This will require you to use your @ontariotechu.net e-mail account. Note the location of the downloaded OVA file on your computer.

    Note

    This file is different from the one you downloaded in step 1. The OVA file is a virtual machine template file that has some pre-configured settings you’ll use for this lab. The ISO file is the actual Cisco IOS-XE CSR1000v virtual machine image, which you will install into the virtual machine template you downloaded as an OVA file, in the next step.

Step 3: Install the CSR1000v VMπŸ”—

  1. Open Oracle VirtualBox Manager if it’s not already open.

  2. Select File > Import Appliance or press Ctrl+I.

  3. The source of the appliance is Local File System. Click in the File box and browse to the location of the downloaded CSR1000v_for_VirtualBox.ova file, and click Finish to start the import process. You will now see the CSR1000v VM added to VirtualBox.

  4. Once the import process is complete, click the Settings button on the CSR1000v VM.

  5. Select Network from the menu on the left, then change the Attached to: dropdown from Host-only Adapter to NAT Network. Ensure the name field says DEVASC and click OK.

    VirtualBox network settings for the CSR1000v VM

    Note

    NAT Network will allow the CSR1000v VM to communicate with the DEVASC VM that’s already running.

Step 4: Update the installation ISO locationπŸ”—

  1. Click the Settings button on the CSR1000v VM.

  2. Click Storage from the menu on the left, then select the first CD device shown under Storage Devices. It should currently say csr1000v-universalk9-install_for_VirtualBox_3.iso, and is likely the second item in the list, after the CSR1000v-disk.vdi hard drive.

  3. With the CD drive selected, click the small blue disc icon next to IDE Primary Device 1 on the far right and select Choose a disk file… from the dropdown menu

    Virtualbox storage settings for the CSR1000v VM

  4. Select the ISO file you downloaded in step 1, called csr1000v-universalk9.16.09.05.iso, then click Open.

    Important

    Do NOT change the Second CD Drive settings. That is used for the initial configuration of the router.

  5. Click OK to save the Virtual Machine settings.

Step 5: Start CSR1000v VMπŸ”—

  1. Select the CSR1000v VM and click Start.

  2. During the loading process you will see several messages including a message to Press any key to continue. Press any key to continue the installation.

  3. A selection screen will eventually appear where you can choose different configuration options. Do not choose any configuration options. Installation will continue on its own. If it does not start automatically after a few seconds, ensure the first option is selected and press Enter.

  4. Wait for the initial installation process to be completed. This will take several minutes the first time you boot the CSR1000v and it will likely need to reboot at least once. Subsequent loads of the VM will be much faster once the image has been installed.

    You will begin to see IOS messages from different processes including %SSH, %PKI and %CRYPTO_ENGINE. After a few minutes the messages will stop, and the router has finished loading. For example:

    Initial boot screen of the CSR1kv VM

    Tip

    You can press Host+C or select View > Scaled Mode to make the CSR1000v window scalable and easier to read. The Host key defaults to the right-hand Ctrl key on your keyboard.

  5. Within the VM window, press Enter. You should see a Cisco Networking Academy message and the router prompt: CSR1kv>.

    Cisco Networking Academy message that appears on first boot

  6. Enter enable for the privileged EXEC prompt. There is no enable password.

    CSR1kv> enable
    CSR1kv#
    

    Note

    By default, the Host key is set to the right-hand Ctrl key on your keyboard. This key is used for navigating the VirtualBox interface, such as entering/leaving full screen mode (Host+F). If you find your cursor is stuck inside of the CSR100v VM window, pressing the Right Ctrl key should let you escape.

Part 2: Verify Communications to CSR1000v VMπŸ”—

In this Part, you will verify communications between devices:

Step 1: Verify the CSR1000v IPv4 addressπŸ”—

  1. From the CSR1000v VM, use the show ip interface brief command to verify the IPv4 address of the GigabitEthernet1 interface. The CSR1000v should be using the IPv4 address from the 10.0.2.0/24 address space.

    CSR1kv# show ip interface brief
    Interface              IP-Address      OK? Method Status                Protocol
    GigabitEthernet1       10.0.2.5        YES DHCP   up                    up      
    CSR1kv#
    

    Important

    Make note of this address and use it in the rest of this lab in place of the default of 10.0.2.5.

Step 2: Ping the CSR1000v VM from the DEVASC VM VMπŸ”—

  1. Switch to the DEVASC VM VM.

  2. Open a Terminal window.

  3. Ping the CSR1000v VM at its IPv4 address (press Ctrl+C to stop the pings). Make sure to replace 10.0.2.5 with the IP address you noted at the end of Step 1.

    devasc@labvm:~/labs/devnet-src/ansible$ ping 10.0.2.5
    PING 10.0.2.5 (10.0.2.5) 56(84) bytes of data.
    64 bytes from 10.0.2.5: icmp_seq=1 ttl=255 time=7.62 ms
    64 bytes from 10.0.2.5: icmp_seq=2 ttl=255 time=1.27 ms
    64 bytes from 10.0.2.5: icmp_seq=3 ttl=255 time=1.39 ms
    64 bytes from 10.0.2.5: icmp_seq=4 ttl=255 time=1.59 ms
    ^C
    --- 10.0.2.5 ping statistics ---
    4 packets transmitted, 4 received, 0% packet loss, time 3011ms
    devasc@labvm:~/labs/devnet-src/ansible$
    

    Important

    Ensure that these pings are successful, and not timing out or giving other errors, before moving on.

Step 3: Establish a secure shell (SSH) session with the CSR1000vπŸ”—

Some of the tasks you will complete in later labs will require an SSH session with the CSR1000v.

  1. Connect to the CSR1000v with SSH from the DEVASC VM. If you are prompted to accept the RSA key, type yes. Use the password cisco123! to authenticate. Notice that you are automatically in privileged EXEC mode. Type exit to end the SSH session. Remember to use the IP address of your CSR1000v VM in place of the one used in the example.

    devasc@labvm:~/labs/devnet-src/ansible$ ssh cisco@10.0.2.5
    Password:
    
    
    *                                           *
    **                                         **
    ***                                       ***
    ***   Cisco Networking Academy            ***
    ***                                       ***
    ***   This software is provided for       ***
    ***    Educational Purposes               ***
    ***     Only in Networking Academies      ***
    ***                                       ***
    **                                         **
    *                                           *
    
    
    CSR1kv# exit
    Connection to 10.0.2.5 closed by remote host.
    Connection to 10.0.2.5 closed.
    devasc@labvm:~/labs/devnet-src/ansible$
    

Step 4: From the DEVASC VM, access the CSR1000v WebUI (Web User Interface)πŸ”—

  1. Open the Chromium Web Browser on the DEVASC VM.

  2. For the URL enter: https://10.0.2.5

    Note

    Be sure to use https and the IP address of your CSR1000v VM.

  3. If your browser displays a warning similar to, Your connection is not private:

    1. Click Advanced.

    2. Click Proceed to 10.0.2.5 (unsafe).

  4. You will now see a LOGIN screen. Enter the following:

    1. Username: cisco

    2. Password: cisco123!

    3. Click LOGIN NOW.

    You will now see the Dashboard for the CSR1000v. You are now accessing the CSR1000v's WebUI from the DEVASC virtual machine.

    Screenshot of the CSR1kv web interface

    Note

    At any time when you are done with the CSR1000v VM, simply shut it down from VirtualBox Manager. If you are continuing immediately to the next part of the lab, leave the CSR1000v VM running.

6.4 Use Ansible to Back Up and Configure a DeviceπŸ”—

ObjectivesπŸ”—

    Part 1: Configure Ansible
    Part 2: Use Ansible to Back up a Configuration
    Part 3: Use Ansible to Configure a Device

BackgroundπŸ”—

In this lab, you will explore the fundamentals of how to use Ansible to automate some basic device management tasks. First, you will configure Ansible in your DEVASC VM. Next, you will use Ansible to connect to the CSR1000v and back up its configuration. Finally, you will configure the CSR1000v with IPv6 addressing using Ansible.

InstructionsπŸ”—

Part 1: Configure AnsibleπŸ”—

In this part, you will configure Ansible to run from a specific directory.

Important

Ensure that both the DEVASC VM and the CSR100v VM are running and completely loaded before starting this lab.

Step 1: Open the Ansible directory in VS CodeπŸ”—

  1. Open VS Code .

  2. Click File > Open Folder... and navigate to the ~/labs/devnet-src/ansible folder.

  3. Click Open.

  4. The two subdirectories for the Ansible labs are now loaded in the VS Code EXPLORER pane for your convenience. In this part of the lab, you will work with the ansible-csr1000v directory.

    Note

    If prompted, check the Trust the authors of all files in the parent folder 'devnet-src' box, and click Yes, I trust the authors

Step 2: Edit the Ansible inventory fileπŸ”—

Ansible uses an inventory file called hosts that contains device information used by Ansible playbooks. The default location for the Ansible inventory file is /etc/ansible/hosts as specified in the default ansible.cfg in the same /etc/ansible directory.

These default files are used when Ansible is run globally. However, in this lab you will run Ansible from the ansible-csr1000v directory. Therefore, you need separate hosts and ansible.cfg files for each lab.

Note

The terms hosts file and inventory file are synonymous and will be used interchangeably throughout the Ansible labs.

The Ansible inventory file defines the devices and groups of devices that are used by the Ansible playbook. The file can be in one of many formats, including YAML and INI, depending on your Ansible environment. The inventory file can list devices by IP address or fully qualified domain name (FQDN) and may include host specific parameters as well.

  1. In VS Code, open the hosts file in the ansible-csr1000v directory (not the ansible-apache directory!).

  2. Add the following lines to the hosts file and save (use the IP address of your CSR1kv VM from lab 6.2). Note that the line starting with CSR1kv is all one line, ending with the ansible_network_os parameter.

    # Enter the hosts or devices for Ansible playbooks
    CSR1kv ansible_user=cisco ansible_password=cisco123! ansible_host=10.0.2.5 ansible_network_os=ios
    

    After the comment (#), the hosts file begins with an alias, CSR1kv. An alias is used from within the Ansible playbook to reference a device. After the alias, the hosts file specifies three variables that will be used by the Ansible playbook to access the device. These are the SSH credentials Ansible needs to securely access the CSR1000v VM.

    • ansible_user is a variable containing the username used to connect to the remote device. Without this, the user that is running the Ansible playbook would be used.

    • ansible_password is a variable containing the corresponding password for ansible_user. If not specified, the SSH key would be used.

    • ansible_host is a variable containing the IP address or FQDN of the device.

    • ansible_network_os is a variable containing the operating system of the network device, in this case, Cisco IOS

  3. Save the hosts file when you are done.

Step 3: Display the Ansible version and default ansible.cfg locationπŸ”—

  1. To see where Ansible stores the default ansible.cfg file, first open a terminal window and navigate to ~/labs/devnet-src/ansible.

    devasc@labvm:~/$ cd ~/labs/devnet-src/ansible
    devasc@labvm:~/labs/devnet-src/ansible$
    
  2. Type ansible to get a list of the ansible commands. Notice the --version option.

    devasc@labvm:~/labs/devnet-src/ansible$ ansible
    usage: ansible [-h] [--version] [-v] [-b] [--become-method BECOME_METHOD]
                   [--become-user BECOME_USER] [-K] [-i INVENTORY] [--list-hosts]
                   [-l SUBSET] [-P POLL_INTERVAL] [-B SECONDS] [-o] [-t TREE] [-k]
                   [--private-key PRIVATE_KEY_FILE] [-u REMOTE_USER]
                   [-c CONNECTION] [-T TIMEOUT]
                   [--ssh-common-args SSH_COMMON_ARGS]
    <output omitted>
    
    devasc@labvm:~/labs/devnet-src/ansible$
    
  3. Use the ansible --version command to display version information. Notice that this lab is using version 2.9.9. Ansible also includes certain default files in the output, including a default configuration file, ansible.cfg.

    devasc@labvm:~/labs/devnet-src/ansible$ ansible --version
    ansible 2.9.9
      config file = /etc/ansible/ansible.cfg
      configured module search path = ['/home/devasc/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
      ansible python module location = /usr/lib/python3/dist-packages/ansible
      executable location = /usr/bin/ansible
      python version = 3.8.2 (default, Apr 27 2020, 15:53:34) [GCC 9.3.0]
    devasc@labvm:~/labs/devnet-src/ansible$
    

Step 4: Display the default ansible.cfg fileπŸ”—

The ansible.cfg file is used by Ansible to set certain default values. These values can be modified.

  1. Using the default path displayed in the ansible --version command, display the default configuration file. Notice this is a very long file. You can pipe the output of the cat command to more so that it displays one page at a time. Highlighted are the entries that will be in your ansible.cfg file for this lab. Don't change any settings in this file!

    devasc@labvm:~/labs/devnet-src/ansible$ cat /etc/ansible/ansible.cfg | more
    
    # config file for ansible -- https://ansible.com/
    # ===============================================
    
    # nearly all parameters can be overridden in ansible-playbook
    # or with command line flags. ansible will read ANSIBLE_CONFIG,
    # ansible.cfg in the current working directory, .ansible.cfg in
    # the home directory or /etc/ansible/ansible.cfg, whichever it
    # finds first
    
    [defaults]
    
    # some basic default values...
    
    #inventory = /etc/ansible/hosts
    <output omitted>
    
    # uncomment this to disable SSH key host checking
    #host_key_checking = False
    <output omitted>
    
    # retry files
    # When a playbook fails a .retry file can be created that will be placed in ~/
    # You can enable this feature by setting retry_files_enabled to True
    # and you can change the location of the files by setting retry_files_save_path
    
    #retry_files_enabled = False
    <output omitted>
    
    devasc@labvm:~/labs/devnet-src/ansible$
    

    Notice that Ansible shows that the inventory hosts file it will use by default is /etc/ansible/hosts. In a previous step, you edited the inventory hosts file in the ansible-csr1000v directory. In the next step you will edit a new ansible.cfg file to use the hosts inventory file that you created earlier instead of the default one.

Step 5: Change the location of the ansible.cfg fileπŸ”—

  1. Ansible will use the config file located in /etc/ansible/ansible.cfg unless there is an ansible.cfg file in the current directory. Change to the ansible-csr1000v directory. There is already a placeholder ansible.cfg file in this directory. Display the current location of ansible.cfg with the ansible --version command.

    devasc@labvm:~/labs/devnet-src/ansible$ cd ansible-csr1000v/
    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ ansible --version
    ansible 2.9.9
      config file = /home/devasc/labs/devnet-src/ansible/ansible-csr1000v/ansible.cfg
    <output omitted>
    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$
    
  2. Display the file to see that it is empty, except for a single comment. You will edit this file in the next step.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ cat ansible.cfg
    # Add to this file for the Ansible lab
    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$
    

Step 6: Edit the ansible.cfg fileπŸ”—

Now, you need to edit your ~/labs/devnet-src/ansible/ansible-csr1000v/ansible.cfg file to include the location of your hosts inventory file. Remember, the default config file in /etc/ansible/ansible.cfg uses the inventory file in /etc/ansible/hosts.

  1. Open the ~/labs/devnet-src/ansible/ansible-csr1000v/ansible.cfg file in VS Code .
  2. You can remove the comment. Add the following lines to the file and save it.

    # config file for ansible-csr1000v
    [defaults]
    # Use local hosts file in this folder
    inventory=./hosts
    host_key_checking = False # Don't worry about RSA Fingerprints
    retry_files_enabled = False # Do not create "retry files"
    deprecation_warnings = False # Do not show warnings
    

    Like Python, the # is used for comments within the ansible.cfg file. If the entry refers to a file name such as inventory=./hosts the comment cannot come after the entry. Ansible treats the # and the comment that follows as part of the filename.

    Therefore, in these cases, the # comment must be on a separate line. However, variables can have a comment on the same line as shown for host_key_checking and retry_files_enabled.

    The ansible.cfg file tells Ansible where to find the inventory file and sets certain default parameters. The information you entered in your ansible.cfg file is as follows:

    • inventory=./hosts - Your inventory file is the hosts file in the current directory.

    • host_key_checking = False - The local development environment does not have SSH keys set up. You have set the host_key_checking to False, which is the default. In a production network, host_key_checking would be set to True.

    • retry_files_enabled = False - When Ansible has problems running playbooks for a host, it will output the name of the host into a file in the current directory ending in .retry. To prevent clutter, it is common to disable this setting.

    • deprecation_warnings=False - Deprecation warnings indicate usage of legacy features that are slated for removal in a future release of Ansible. You have disabled this warning.

Part 2: Use Ansible to Back up a ConfigurationπŸ”—

In this part, you will create an Ansible playbook that will automate the process of backing up the configuration of the CSR1000v. Playbooks are at the center of Ansible. When you want Ansible to get information or perform an action on a device or group of devices, you run a playbook to get the job done.

An Ansible playbook is a YAML file containing one or more plays. Each play is a collection of tasks.

  • A play is a matching set of tasks to a device or group of devices.

  • A task is a single action that references a module to run along with any input arguments and actions. These tasks can be simple or complex depending on the necessary permissions, the order to run the tasks, and so on.

A playbook may also contain roles. A role is a mechanism for breaking a playbook into multiple components or files, simplifying the playbook and making it easier to reuse. For example, the common role is used to store tasks that can be used across all of your playbooks. Roles are beyond the scope of this lab.

The Ansible YAML playbook includes objects, lists and modules.

  • A YAML object is one or more key/value pairs. Key/value pairs are separated by a colon without the use of quotation marks, for example hosts: CSR1kv.

  • An object can contain other objects such as a list. YAML uses lists or arrays. A hyphen - is used for each element in the list.

  • Ansible ships with a number of modules (called the module library) that can be executed directly on remote hosts or through playbooks. An example is the ios_command module used to send commands to a Cisco IOS device and return the results. Each task typically consists of one or more Ansible modules.

You run an Ansible playbook using the ansible-playbook command, for example:

ansible-playbook backup_cisco_router_playbook.yaml -i hosts

The ansible-playbook command uses parameters to specify:

  • The playbook you want to run (backup_cisco_router_playbook.yaml)

  • The inventory file and its location (-i hosts).

Step 1: Create your Ansible playbookπŸ”—

The Ansible playbook is a YAML file. Make sure you use the proper YAML indentation. Every space and dash is significant. You may lose some formatting if you copy and paste the code in this lab, therefore, it's recommend you write this code out manually.

  1. In VS Code , create a new file in the ansible-csr1000v directory called backup_cisco_router_playbook.yaml.

    Important

    Be careful to use this exact filename for the autograder to grade your work properly!

  2. Add the following information to the file (indents are 2 spaces each). Save the file when you are done.

    ---
    - name: AUTOMATIC BACKUP OF RUNNING-CONFIG
      hosts: CSR1kv
      gather_facts: false
      connection: network_cli
    
      tasks:
        - name: DISPLAYING THE RUNNING-CONFIG
          ios_command:
            commands:
              - show running-config
          register: config
    
        - name: SAVE OUTPUT TO ./backups/
        copy:
            content: "{{ config.stdout[0] }}"
            dest: "backups/show_run_{{ inventory_hostname }}.txt"
    

Step 2: Examine your Ansible playbookπŸ”—

The playbook you have created contains one play with two tasks. The following is an explanation of your playbook:

  • --- This is at the beginning of every YAML file, which indicates to YAML that this is a separate document. Each file may contain multiple documents separated by ---

  • name: AUTOMATIC BACKUP OF RUNNING-CONFIG - This is the name of the play.

  • hosts: CSR1kv - This is the alias of the device in the previously configured hosts file. By referring to this alias in your playbook, the playbook can use all the parameters associated with this inventory file entry which includes the username, password, and IP address of the device.

  • gather_facts: false - At the start of a playbook, Ansible will gather facts about the remote device, such as the OS version, IP addresses, and hardware. This is not needed for our particular playbook, but is often very useful for automating many devices at once.

  • connection: network_cli - Uses a plugin specifically for connecting to the CLI of network devices.

  • tasks: - This keyword indicates one or more tasks to be performed.

The first task is to display the running-config.

  • name: DISPLAYING THE RUNNING-CONFIG - The name of this task.

  • ios_command: - This is an Ansible module that is used to send commands to a Cisco IOS device and return the results read from the device. However, it does not support configuration commands. The ios_config module is used for this purpose, as you will see in the next Part of this lab.

Note

In the Linux terminal, you can use the ansible-doc <module_name> command to view the manual pages for any module and the parameters associated with that module. (e.g. ansible-doc ios_command)

  • commands: - This parameter is associated with the ios_command module. It is used to list the Cisco IOS commands in the playbook that are to be sent to the remote device. The resulting output from the command is returned.

  • show running-config - This is the Cisco IOS command sent using the ios_command module.

  • register: config - Ansible includes registers used to capture output of a task to a variable. This entry specifies that the output from the previous show running-config command will be stored in the variable config.

The second task is to save the output:

  • name: SAVE OUTPUT TO ./backups/ - The name of this task

  • copy: - This is an Ansible module used to copy files to a remote location. There are two parameters associated with this module:

    • content: "{{ config.stdout[0] }}" - The specified value for this parameter is the data stored in the config variable, the Ansible register variable used in the previous task. Standard output (stdout) is the default file descriptor where a process can write output used in Unix-like operating systems, such as Linux and Mac OS X.

    • dest: "backups/show_run_{{ inventory_hostname }}.txt" - This is the path and file name to where the file should be copied. The inventory_hostname variable is an Ansible "magic variable" that automatically uses the hostname as configured in the hosts file. In your case, recall that this is CSR1kv. This parameter results in a file named show_run_CSR1kv.txt stored in the backups directory. The file will contain the output of the show running-config command. You will create the backups directory in the next step.

Step 3: Run the Ansible backup PlaybookπŸ”—

  1. In Part 1, you started the CSR1000v VM. Ping it to verify you can access it (use the address of your CSR1kv, which might not be the same as the example). Enter Ctrl+C to abort the ping.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ ping 10.0.2.5
    PING 10.0.2.5 (10.0.2.5) 56(84) bytes of data.
    64 bytes from 10.0.2.5: icmp_seq=1 ttl=63 time=0.913 ms
    64 bytes from 10.0.2.5: icmp_seq=2 ttl=63 time=0.875 ms
    ^C
    --- 10.0.2.5 ping statistics ---
    2 packets transmitted, 2 received, 0% packet loss, time 1000ms
    rtt min/avg/max/mdev = 0.875/0.894/0.913/0.019 ms
    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$
    
  2. Create the backups directory. As indicated in the last line of your playbook, this is the directory where the backup configuration file will be stored.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ mkdir backups
    

    Important

    Make sure you are still in the ~/labs/devnet-src/ansible/ansible-csr1000v when you run the mkdir command.

  3. Now you can run the Ansible playbook using the ansible-playbook command:

    Ansible Shell Session
    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ ansible-playbook backup_cisco_router_playbook.yaml
    
    PLAY [AUTOMATIC BACKUP OF RUNNING-CONFIG] ******************************************************************************
    
    TASK [DISPLAYING THE RUNNING-CONFIG] ***********************************************************************************
    ok: [CSR1kv]
    
    TASK [SAVE OUTPUT TO ./backups/] ***************************************************************************************
    changed: [CSR1kv]
    
    PLAY RECAP *************************************************************************************************************
    CSR1kv                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$
    

    Note

    In many examples you will see the playbook run using the -i <inventory-filename> option. For example:

    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ ansible-playbook backup_cisco_router_playbook.yaml -i hosts
    

    This option tells Ansible the location and name of the inventory file; the list of devices the playbook will use. This option is not necessary because you configured the inventory file name and location in your local ansible.cfg file: inventory=./hosts. You can use the -i <inventory-filename> option to override the information in the ansible.cfg file.

    The PLAY RECAP should display ok=2 changed=1 indicating a successful playbook execution.

    If your Ansible playbook fails, some of the things to check in your playbook are:

    • Make sure your hosts and ansible.cfg files are correct.

    • Make sure the YAML indentation is correct.

    • Make sure your IOS command is correct.

    • Check all the Ansible playbook syntax.

    • Verify you can ping the CSR1000v.

    If you continue to have problems, try typing one line at a time and running the playbook each time.

Step 4: Verify the backup file has been createdπŸ”—

  1. In VS Code , open the backups folder and open the show_run_CSR1kv.txt file. You can also use the terminal window to cat the file with cat backups/show_run_CSR1kv.txt. You now have a backup of the CSR1000v configuration.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ cat backups/show_run_CSR1kv.txt
    Building configuration...
    
    Current configuration : 4004 bytes
    !
    ! Last configuration change at 23:57:14 UTC Sun May 17 2020
    !
    version 16.9
    service timestamps debug datetime msec
    service timestamps log datetime msec
    platform qfp utilization monitor load 80
    no platform punt-keepalive disable-kernel-core
    platform console virtual
    !
    hostname CSR1kv
    !
    
    <output omitted>
    

Part 3: Use Ansible to Configure a DeviceπŸ”—

In this part, you will create another Ansible playbook to configure IPv6 addressing on the CSR1000v router.

Step 1: View your hosts inventory fileπŸ”—

  1. Re-examine your hosts inventory file. As a reminder, this file contains the alias CSR1kv and three inventory variables for the username, password, and host IP address. The playbook for this part will also use this file and the ansible.cfg file you created early in the lab.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ cat hosts
    # Enter the hosts or devices for Ansible playbooks
    CSR1kv ansible_user=cisco ansible_password=cisco123! ansible_host=10.0.2.5 ansible_network_os=ios
    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$
    

Step 2: Create a new playbookπŸ”—

  1. In VS Code , create a new file in the ansible-csr1000v directory called cisco_router_ipv6_config_playbook.yaml.

    Important

    Be careful to use this exact filename for the autograder to grade your work properly!

  2. Add the following information to the file. Make sure you use the proper YAML indentation. Every space and dash is significant. You may lose some formatting if you copy and paste the code in this lab, therefore, it's recommend you write this code out manually. Save the file when you are done.

    ---
    - name: CONFIGURE IPv6 ADDRESSING
      hosts: CSR1kv
      gather_facts: false
      connection: network_cli
    
      tasks:
      - name: SET IPv6 ADDRESS
        ios_config:
          parents: "interface GigabitEthernet1"
          lines:
            - description IPv6 ADDRESS
            - ipv6 address 2001:DB8:ACAD:1::1/64
            - ipv6 address FE80::1:1 link-local
    
      - name: SHOW IPv6 INTERFACE BRIEF
        ios_command:
          commands:
            - show ipv6 interface brief
        register: output
    
      - name: SAVE OUTPUT ./ios_configurations/
        copy:
          content: "{{ output.stdout[0] }}"
          dest: "ios_configurations/IPv6_output_{{ inventory_hostname }}.txt"
    

Step 3: Examine your Ansible playbookπŸ”—

Much of this playbook is similar to the playbook you created in the previous part. The main difference is the first task SET IPv6 ADDRESS.

The following is a brief description of the items in the task:

  • ios_config: - This is an Ansible module used to configure an IOS device. You can use the ansible-doc ios_config command to see the details for the parents and lines parameters used in this playbook.

  • parents: "interface GigabitEthernet1" - This parameter indicates the interface to configure.

  • lines: - An ordered set of IOS commands are configured in this section, specifying the IPv6 addressing information for the GigabitEthernet1 interface.

The rest of the playbook is similar to the tasks in the previous part. The second task uses the ios_command module and the command show ipv6 interface brief to display output and send it to the register output.

The last task saves the information in the register output to a file IPv6_output_CSR1kv.txt in the ios_configurations subdirectory.

Note

for Cisco IOS configuration playbooks to be considered idempotent, you must use the full commands as they would appear in the running configuration, not shortened versions (e.g., use no shutdown rather than no shut, or interface GigabitEthernet1 rather than int g1).

Step 4: Run the Ansible playbook to configure IPv6 addressing on the CSR1000v VMπŸ”—

  1. In Part 1, you started the CSR1000v VM. Ping it to verify you can still access it. Enter Ctrl+C to abort the ping.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ ping 10.0.2.5
    PING 10.0.2.5 (10.0.2.5) 56(84) bytes of data.
    64 bytes from 10.0.2.5: icmp_seq=1 ttl=63 time=0.913 ms
    64 bytes from 10.0.2.5: icmp_seq=2 ttl=63 time=0.875 ms
    ^C
    --- 10.0.2.5 ping statistics ---
    2 packets transmitted, 2 received, 0% packet loss, time 1000ms
    rtt min/avg/max/mdev = 0.875/0.894/0.913/0.019 ms
    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$
    
  2. Create the directory ios_configurations. As indicated in the last line of your playbook, this is the directory where the output for the show ipv6 interface brief command will be stored.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ mkdir ios_configurations
    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$
    
  3. Now you can run the Ansible playbook using the ansible-playbook command. The -v verbose option can be used to display the tasks being performed in the playbook.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ ansible-playbook -v cisco_router_ipv6_config_playbook.yaml
    Using /home/devasc/labs/devnet-src/ansible/ansible-csr1000v/ansible.cfg as config file
    
    PLAY [CONFIGURE IPv6 ADDRESSING] ***********************************************
    
    TASK [SET IPv6 ADDRESS] ********************************************************
    changed: [CSR1kv] => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "banners": {}, "changed": true, "commands": ["interface GigabitEthernet1", "description IPv6 ADDRESS", "ipv6 address 2001:DB8:ACAD:1::1/64", "ipv6 address FE80::1:1 link-local"], "updates": ["interface GigabitEthernet1", "description IPv6 ADDRESS", "ipv6 address 2001:DB8:ACAD:1::1/64", "ipv6 address FE80::1:1 link-local"]}
    
    TASK [SHOW IPv6 INTERFACE BRIEF] ***********************************************
    ok: [CSR1kv] => {"changed": false, "stdout": ["GigabitEthernet1 [up/up]\n FE80::1:1\n 2001:DB8:ACAD:1::1"], "stdout_lines": [["GigabitEthernet1 [up/up]", " FE80::1:1", " 2001:DB8:ACAD:1::1"]]}
    
    TASK [SAVE OUTPUT ./ios_configurations/] ***************************************
    changed: [CSR1kv] => {"changed": true, "checksum": "60784fbaae4bd825b7d4f121c450effe529b553c", "dest": "ios_configurations/IPv6_output_CSR1kv.txt", "gid": 900, "group": "devasc", "md5sum": "56e879f15e6e776cf131cec5abfc1886", "mode": "0664", "owner": "devasc", "size": 67, "src": "/home/devasc/.ansible/tmp/ansible-local-3897abxawwgb/ansible-tmp-1710014758.4905267-3965-179789089872527/source", "state": "file", "uid": 900}
    
    PLAY RECAP *********************************************************************
    
    CSR1kv                     : ok=3  changed=2  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0
    
    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$
    

    Note

    The first time you run the playbook, the PLAY RECAP should display ok=3 changed=2 and failed=0 indicating a successful execution.

Step 5: Verify the file of the output has been createdπŸ”—

  1. In VS Code , open the ios_configurations folder and click the IPv6_output_CSR1kv.txt file. You can also use the terminal window to view the file with cat ios_configurations/IPv6_output_CSR1kv.txt. This displays the IPv6 addresses of GigabitEthernet1.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ cat ios_configurations/IPv6_output_CSR1kv.txt
    GigabitEthernet1       [up/up]
        FE80::1:1
        2001:DB8:ACAD:1::1
    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$
    

Step 6: Verify the configuration has changed on the CSR1kv VMπŸ”—

  1. Switch to the CSR1kv VM and enter the command show ipv6 interface brief and confirm that you see the newly configured IPv6 address on GigabitEthernet1.

    CSR1kv# show ipv6 interface brief
    GigabitEthernet1       [up/up]
        FE80::1:1
        2001:DB8:ACAD:1::1
    CSR1kv#
    

Step 7: Test the idempotency of the Ansible playbookπŸ”—

Idempotency means that running the same procedure multiple times will always result in the same end state. In the case of this Ansible playbook, Ansible should not make any changes to the switch or saved output file if the IPv6 address is already configured on GigabitEthernet1.

  1. Execute the playbook again and watch the output to see how it is different from the first time you ran it.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ ansible-playbook -v cisco_router_ipv6_config_playbook.yaml
    Using /home/devasc/labs/devnet-src/ansible/ansible-csr1000v/ansible.cfg as config file
    
    PLAY [CONFIGURE IPv6 ADDRESSING] ***********************************************
    
    TASK [SET IPv6 ADDRESS] ********************************************************
    ok: [CSR1kv] => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "changed": false}
    
    TASK [SHOW IPv6 INTERFACE BRIEF] ***********************************************
    ok: [CSR1kv] => {"changed": false, "stdout": ["GigabitEthernet1 [up/up]\n FE80::1:1\n 2001:DB8:ACAD:1::1"], "stdout_lines": [["GigabitEthernet1 [up/up]", " FE80::1:1", " 2001:DB8:ACAD:1::1"]]}
    
    TASK [SAVE OUTPUT ./ios_configurations/] ***************************************
    ok: [CSR1kv] => {"changed": false, "checksum": "60784fbaae4bd825b7d4f121c450effe529b553c", "dest": "ios_configurations/IPv6_output_CSR1kv.txt", "gid": 900, "group": "devasc", "mode": "0664", "owner": "devasc", "path": "ios_configurations/IPv6_output_CSR1kv.txt", "size": 67, "state": "file", "uid": 900}
    
    PLAY RECAP *********************************************************************
    
    CSR1kv                     : ok=3  changed=0  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0
    

    Notice that the output now says ok=3 and changed=0. Ansible has recognized that everything is already at the desired end state and made no changes (idempotency). If you watch the timestamp on the IPv6_output_CSR1kv.txt file, you’ll also notice that it does not change when you rerun the playbook.

Step 8: Commit the changes to the repositoryπŸ”—

  1. Use git status to see which files have been added and modified since the last commit.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ git status
    On branch main
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git restore <file>..." to discard changes in working directory)
            modified: ansible.cfg
            modified: hosts
    
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
            backup_cisco_router_playbook.yaml
            backups/
            cisco_router_ipv6_config_playbook.yaml
            ios_configurations/
    
    no changes added to commit (use "git add" and/or "git commit -a")
    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$
    
  2. Add all the files and folders to the staging area with git add . (don’t miss the "." at the end). Verify all files have now been staged with git status.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ git add .
    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ git status
    On branch main
    Changes to be committed:
      (use "git restore --staged <file>..." to unstage)
            modified: ansible.cfg
            new file: backup_cisco_router_playbook.yaml
            new file: backups/show_run_CSR1kv.txt
            new file: cisco_router_ipv6_config_playbook.yaml
            modified: hosts
            new file: ios_configurations/IPv6_output_CSR1kv.txt
    
    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$
    
  3. Commit the changes to the local repository using the message Completed Ansible router configuration playbooks.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ git commit -m "Completed Ansible router configuration playbooks"
    [main fa87e3c] Completed Ansible router configuration playbooks
     6 files changed, 239 insertions(+), 1 deletion(-)
     create mode 100644 ansible-csr1000v/backup_cisco_router_playbook.yaml
     create mode 100644 ansible-csr1000v/backups/show_run_CSR1kv.txt
     create mode 100644 ansible-csr1000v/cisco_router_ipv6_config_playbook.yaml
     create mode 100644 ansible-csr1000v/ios_configurations/IPv6_output_CSR1kv.txt
    devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$
    

    Note

    You can now shut down the CSR1kv virtual machine as it is no longer needed for the rest of the lab.

6.5 Use Ansible to Automate Installing a Web ServerπŸ”—

ObjectivesπŸ”—

    Part 1: Configure Ansible
    Part 2: Verify Communications with the Local Webserver
    Part 3: Create Ansible Playbooks to Automate Webserver Installation
    Part 4: Add Options to Your Ansible Playbook for Apache Web Servers

BackgroundπŸ”—

In this lab, you will first configure Ansible so that it can communicate with a webserver application. You will then create a playbook that will automate the process of installing Apache on the webserver. You will also create a customized playbook that installs Apache with specific instructions.

InstructionsπŸ”—

Part 1: Configure AnsibleπŸ”—

The DEVASC VM comes preinstalled with a number of dummy IPv4 addresses you can use for various scenarios and simulations. In this Part, you will configure Ansible to use one of the dummy IPv4 addresses for a local webserver.

Step 1: Enable the SSH serverπŸ”—

  1. Open a new Terminal window in the DEVASC VM

  2. The SSH server is disabled in the DEVASC VM, along with other services that are typically not required. Start it with the following command.

    devasc@labvm:~/labs/devnet-src/ansible$ sudo systemctl start ssh
    devasc@labvm:~/labs/devnet-src/ansible$
    

    Note

    The SSH server and sshpass utility have already been installed in your VM. For your reference, these are installed using the following commands (you do not need to run these now!): Install SSH

    devasc@labvm:~/labs/devnet-src/ansible$ sudo apt-get install openssh-server
    

    Install sshpass

    devasc@labvm:~/labs/devnet-src/ansible$ sudo apt-get install sshpass
    

Step 2: Open the ansible directory in VS CodeπŸ”—

  1. Open VS Code .

  2. Click File > Open Folder... and navigate to the /labs/devnet-src/ansible folder if it’s not already open.

  3. Click Open.

  4. The two subdirectories for the Ansible labs are now loaded in the VS Code EXPLORER pane for your convenience. In this lab, you will work with the ansible-apache directory.

    Note

    If prompted, check the Trust the authors of all files in the parent folder β€˜devnet-src’ box, and click Yes, I trust the authors

Step 3: Edit the Ansible inventory fileπŸ”—

  1. Open the hosts file in the ansible-apache directory (not ansible-csr1000v).

  2. Add the following lines to the hosts file and save.

    [webservers]
    192.0.2.3 ansible_ssh_user=devasc ansible_ssh_pass=Cisco123!
    
  3. The credentials devasc and Cisco123! are admin credentials for the DEVASC VM. The IPv4 address you will use for this lab is 192.0.2.3. This is a static IPv4 address on the VM under the dummy0 interface, as shown in the output for the ip addr command.

    devasc@labvm:~/labs/devnet-src/ansible$ ip addr
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host 
           valid_lft forever preferred_lft forever
    2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
        link/ether 08:00:27:97:ae:11 brd ff:ff:ff:ff:ff:ff
        inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic enp0s3
           valid_lft 45882sec preferred_lft 45882sec
        inet6 fe80::a00:27ff:fe97:ae11/64 scope link 
           valid_lft forever preferred_lft forever
    3: dummy0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
        link/ether a6:44:a7:e8:6a:9e brd ff:ff:ff:ff:ff:ff
        inet 192.0.2.1/32 scope global dummy0
           valid_lft forever preferred_lft forever
        inet 192.0.2.2/32 scope global dummy0
           valid_lft forever preferred_lft forever
        inet 192.0.2.3/32 scope global dummy0
           valid_lft forever preferred_lft forever
        inet 192.0.2.4/32 scope global dummy0
           valid_lft forever preferred_lft forever
        inet 192.0.2.5/32 scope global dummy0
           valid_lft forever preferred_lft forever
        inet6 fe80::a444:a7ff:fee8:6a9e/64 scope link 
           valid_lft forever preferred_lft forever
    4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
        link/ether 02:42:9c:cb:fc:7c brd ff:ff:ff:ff:ff:ff
        inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
           valid_lft forever preferred_lft forever
    devasc@labvm:~/labs/devnet-src/ansible$
    

Step 5: Edit the ansible.cfg fileπŸ”—

  1. In VS Code , open the ansible.cfg in the ansible-apache subdirectory.

  2. You can remove the comment. Add the following lines to the file and save it. The ansible.cfg file tells Ansible where to find the inventory file and sets certain default parameters.

    [defaults]
    # Use local hosts file in this folder
    inventory=./hosts 
    # Don't worry about RSA Fingerprints
    host_key_checking = False 
    # Do not create retry files
    retry_files_enabled = False
    

Part 2: Verify Communications with the Local WebserverπŸ”—

In this Part, you will verify that Ansible can send commands to the local webserver.

Step 1: Use the ping module to verify that Ansible can ping the webserverπŸ”—

  1. In the Terminal window, change to the ansible-apache directory and use the Ansible ping module to verify communications with the devices listed within the webservers group of your hosts inventory file.

    devasc@labvm:~/labs/devnet-src/ansible$ cd ansible-apache
    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ ansible webservers -m ping
    192.0.2.3 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python3"
        },
        "changed": false,
        "ping": "pong"
    }
    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$
    

    Note

    If multiple devices were listed under the webservers group in your hosts inventory file, the output would indicate similar information for each device.

Step 2: Use the command module to verify Ansible can communicate with the webserverπŸ”—

  1. Use the Ansible command module to verify communications with the devices listed within the webservers group of your hosts inventory file. In this example you send the argument -a "/bin/echo hello world" to ask the local webserver to respond with "hello world".

    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ ansible webservers -m command -a "/bin/echo hello world"
    192.0.2.3 | CHANGED | rc=0 >>
    hello world
    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$
    

Part 3: Create Ansible Playbooks to Automate Webserver InstallationπŸ”—

In this Part, you will create two Ansible playbooks. The first playbook will automate the echo test you did in the previous Part.

Imagine you are bringing a hundred webservers online. The [webserver] group in the hosts file would list all the necessary information for each webserver. You can then use a simple playbook to verify communications with all of them with one command.

In the second playbook, you will create and automate the installation of Apache webserver software.

Step 1: Create your Ansible playbook to test your webserver groupπŸ”—

In this step you will create an Ansible playbook to perform the same echo command.

  1. In VS Code , create a new file in the ansible-apache directory called test_apache_playbook.yaml.

    Important

    Be careful to use this exact filename for the autograder to grade your work properly!

  2. Add the following information to the file. Make sure you use the proper YAML indentation. Every space and dash is significant. You may lose some formatting if you copy and paste the code in this lab, therefore, it's recommend you write this code out manually. Save the file when you are done.

    ---
    - hosts: webservers
      tasks:
        - name: run echo command
          command: /bin/echo hello world
    

Step 2: Run the Ansible playbook to test your webserver groupπŸ”—

  1. Run the Ansible playbook using the ansible-playbook command using the -v verbose option. You should see output similar to the following.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ ansible-playbook -v test_apache_playbook.yaml
    Using /home/devasc/labs/ansible/ansible-apache/ansible.cfg as config file
    
    PLAY [webservers] **************************************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [192.0.2.3]
    
    TASK [run echo command] ********************************************************
    changed: [192.0.2.3] => {"changed": true, "cmd": ["/bin/echo", "hello", "world"], "delta": "0:00:00.002062", "end": "2020-05-20 21:35:32.346595", "rc": 0, "start": "2020-05-20 21:35:32.344533", "stderr": "", "stderr_lines": [], "stdout": "hello world", "stdout_lines": ["hello world"]czjqqkd:77}
    
    PLAY RECAP *********************************************************************
    192.0.2.3                  : ok=2  changed=1  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0   
    
    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$
    

Step 3: Create your Ansible playbook to install ApacheπŸ”—

  1. In VS Code , create a new file in the ansible-apache directory called install_apache_playbook.yaml.

    Important

    Be careful to use this exact filename for the autograder to grade your work properly!

  2. Add the following information to the file. Make sure you use the proper YAML indentation. Every space and dash is significant. You may lose some formatting if you copy and paste the code in this lab, therefore, it's recommend you write this code out manually. Save the file when you are done. The highlighted text is explained in the next step.

    ---
    - hosts: webservers
      become: yes
      tasks:
        - name: INSTALL APACHE2
          apt: name=apache2 update_cache=yes state=latest
    
        - name: ENABLE MOD_REWRITE
          apache2_module: name=rewrite state=present
          notify:
            - RESTART APACHE2
    
      handlers:
        - name: RESTART APACHE2
          service: name=apache2 state=restarted 
    

Step 4: Examine your Ansible playbookπŸ”—

The following is an explanation of some of the significant lines in your playbook:

  • hosts: webservers - This references the webservers group of devices in your hosts inventory file. This playbook will be run for all the devices with this group.

  • become: yes - The become keyword activates sudo command execution, which will allow tasks such as installing applications. On a Cisco device, this would be equivalent to using enable to get to Privileged EXEC.

  • apt: - The apt module is used to manage packages and application installations on Linux. In this case, you are telling Ansible to use apt to install the latest version of apache2 if its not already installed.

  • handlers: - Handlers are similar to a task but are not run automatically. They are called by another task, similar to how a function in programming is called. Notice that the task ENABLE MOD_REWRITE calls the handler RESTART APACHE2.

Step 5: Run the Ansible backup to install ApacheπŸ”—

  1. Run the Ansible playbook using the ansible-playbook command using the -v verbose option. The first time Apache installed on your VM, the task INSTALL APACHE2 will take anywhere from 30 seconds to a few minutes depending on your internet speed.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ ansible-playbook install_apache_playbook.yaml
    Using /home/devasc/labs/ansible/ansible-apache/ansible.cfg as config file
    
    PLAY [webservers] **************************************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [192.0.2.3]
    
    TASK [INSTALL APACHE2] *********************************************************
    changed: [192.0.2.3]
    
    TASK [ENABLE MOD_REWRITE] ******************************************************
    changed: [192.0.2.3]
    
    RUNNING HANDLER [RESTART APACHE2] **********************************************
    changed: [192.0.2.3]
    
    PLAY RECAP *********************************************************************
    192.0.2.3                  : ok=4  changed=3  unreachable=0   failed=0  skipped=0  rescued=0  ignored=0    
    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$
    

    Note

    The PLAY RECAP should display ok=4 and failed=0 indicating a successful playbook execution. If you run the playbook again you should get changed=0 rather than changed=3, because the playbook is idempotent and will not make changes if the server is already in the desired state.

Step 6: Verify Apache has been installedπŸ”—

  1. Use the following command to verify that Apache is now installed. Press Q to quit.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ sudo systemctl status apache2
    ● apache2.service - The Apache HTTP Server
         Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
         Active: active (running) since Thu 2026-03-12 22:30:26 UTC; 1min 41s ago
           Docs: https://httpd.apache.org/docs/2.4/
        Process: 17777 ExecStart=/usr/sbin/apachectl start (code=exited, status=0/SUCCESS)
       Main PID: 17801 (apache2)
          Tasks: 55 (limit: 4628)
         Memory: 5.3M
         CGroup: /system.slice/apache2.service
                 β”œβ”€17801 /usr/sbin/apache2 -k start
                 β”œβ”€17803 /usr/sbin/apache2 -k start
                 └─17804 /usr/sbin/apache2 -k start
    
    Mar 12 22:30:26 labvm systemd[1]: Starting The Apache HTTP Server...
    Mar 12 22:30:26 labvm systemd[1]: Started The Apache HTTP Server.
    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$
    
  2. Open the Chromium Web Browser and enter the IPv4 address for your new server, 192.0.2.3, to see the default Apache2 web page.

    Screenshot of the Chromium web browser showing the default Apache2 landing page

Part 4: Add Options to Your Ansible Playbook for Apache Web ServersπŸ”—

In a production environment, the Apache2 default installation is typically customized for the specific features needed by the organization. An Ansible playbook can help automate these configuration tasks, as well. In this part, you will customize your playbook by specifying that the Apache server use a different port number.

Step 1: Create your Ansible playbook for installing ApacheπŸ”—

  1. In VS Code , create a new file in the ansible-apache directory called install_apache_options_playbook.yaml

    Important

    Be careful to use this exact filename for the autograder to grade your work properly!

  2. Add the following information to the file. Make sure you use the proper YAML indentation. Every space and dash is significant. You may lose some formatting if you copy and paste the code in this lab, therefore, it's recommend you write this code out manually. Save the file when you are done.

    ---
    - hosts: webservers
      become: yes
      tasks:
       - name: INSTALL APACHE2
         apt: name=apache2 update_cache=yes state=latest
    
       - name: ENABLE MOD_REWRITE
         apache2_module: name=rewrite state=present
         notify:
           - RESTART APACHE2
    
       - name: APACHE2 LISTEN ON PORT 8081
         lineinfile: dest=/etc/apache2/ports.conf regexp="^Listen 80" line="Listen 8081" state=present
         notify:
           - RESTART APACHE2
    
       - name: APACHE2 VIRTUALHOST ON PORT 8081
         lineinfile: dest=/etc/apache2/sites-available/000-default.conf regexp="^<VirtualHost \*:80>" line="<VirtualHost *:8081>" state=present
         notify:
           - RESTART APACHE2
    
      handlers:
       - name: RESTART APACHE2
         service: name=apache2 state=restarted
    

    Important

    The lines that include lineinfile should each be on one line in your file, including the regexp=, line=, and state= parameters. They may appear on multiple lines on this page due to word wrapping.

    This playlist is very similar to the previous one with the addition of two tasks that have the webservers listen on port 8081 instead of port 80.

    The lineinfile module is used to replace existing lines in the /etc/apache2/ports.conf and /etc/apache2/sites-available/000-default.conf files using Regular Expressions (regexp). You can search the Ansible documentation for more information on the lineinfile module.

Step 2: Examine the two files that will be modified by the playbookπŸ”—

  1. Display the files /etc/apache2/ports.conf and /etc/apache2/sites-available/000-default.conf. Notice the webserver is currently listening on port 80.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ cat /etc/apache2/ports.conf
    # If you just change the port or add more ports here, you will likely also
    # have to change the VirtualHost statement in
    # /etc/apache2/sites-enabled/000-default.conf
    
    Listen 80
    
    <IfModule ssl_module>
            Listen 443
    
    <output omitted>
    
    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ cat /etc/apache2/sites-available/000-default.conf
    <VirtualHost *:80>
            # The ServerName directive sets the request scheme, hostname and port that
            # the server uses to identify itself. This is used when creating
            # redirection URLs. In the context of virtual hosts, the ServerName
    
    <output omitted>
    
    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$
    

Step 3: Run the Ansible PlaybookπŸ”—

  1. Run the Ansible playbook using the ansible-playbook command.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ ansible-playbook install_apache_options_playbook.yaml
    
    PLAY [webservers] **************************************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [192.0.2.3]
    
    TASK [INSTALL APACHE2] *********************************************************
    ok: [192.0.2.3]
    
    TASK [ENABLE MOD_REWRITE] ******************************************************
    ok: [192.0.2.3]
    
    TASK [APACHE2 LISTEN ON PORT 8081] *********************************************
    changed: [192.0.2.3]
    
    TASK [APACHE2 VIRTUALHOST ON PORT 8081] ****************************************
    changed: [192.0.2.3]
    
    RUNNING HANDLER [RESTART APACHE2] **********************************************
    changed: [192.0.2.3]
    
    PLAY RECAP *********************************************************************
    192.0.2.3                  : ok=6  changed=3  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0   
    
    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$
    

    Note

    The PLAY RECAP should display ok=6 and failed=0 indicating a successful playbook execution. You also will see the two PORT tasks are marked as changed. Note if you run the playbook again you should get changed=0 rather than changed=3, because the playbook is idempotent and will not make changes if the server is already in the desired state.

Step 4: Verify that Apache has been installedπŸ”—

  1. View the files /etc/apache2/ports.conf and /etc/apache2/sites-available/000-default.conf again. Notice that the playbook modified these files to listen on port 8081.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ cat /etc/apache2/ports.conf
    # If you just change the port or add more ports here, you will likely also
    # have to change the VirtualHost statement in
    # /etc/apache2/sites-enabled/000-default.conf
    
    Listen 8081
    
    <IfModule ssl_module>
            Listen 443
    </IfModule>
    
    <IfModule mod_gnutls.c>
            Listen 443
    </IfModule>
    
    <output omitted>
    
    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ cat /etc/apache2/sites-available/000-default.conf
    <VirtualHost *:8081>
            # The ServerName directive sets the request scheme, hostname and port that
            # the server uses to identify itself. This is used when creating
            # redirection URLs. In the context of virtual hosts, the ServerName
    
    <output omitted>
    
    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$
    
  2. Open the Chromium web browser and enter the IPv4 address for your new server. But this time specify 8081 as the port number, 192.0.2.3:8081, to see the default Apache2 web page.

    Screenshot of the Chromium web browser showing the default Apache2 landing page, this time on port 8081"

    Note

    Although you can see in the ports.conf file that Apache2 is also listening on port 443, this is for secure HTTP (HTTPS). You have not yet configured Apache2 for secure access. This, of course, would be added to your Ansible playbook, but is beyond the scope of this lab.

Step 5: Push your changes to GitHubπŸ”—

  1. Use git status to see which files have been added and modified since the last commit.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ git status
    On branch main
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git restore <file>..." to discard changes in working directory)
            modified:   ansible.cfg
            modified:   hosts
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
            install_apache_options_playbook.yaml
            install_apache_playbook.yaml
            test_apache_playbook.yaml
    
    no changes added to commit (use "git add" and/or "git commit -a")
    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$
    
  2. Add all the files and folders to the staging area with git add . (don’t miss the "." at the end). Verify all files have now been staged with git status.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ git add .
    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ git status
    On branch main
    Changes to be committed:
      (use "git restore --staged <file>..." to unstage)
            modified:   ansible.cfg
            modified:   hosts
            new file:   install_apache_options_playbook.yaml
            new file:   install_apache_playbook.yaml
            new file:   test_apache_playbook.yaml
    
    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$
    
  3. Commit the changes to the local repository using the message Lab Complete!.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ git commit -m "Lab Complete!"
    [main 3e465ca] Lab Complete!
     5 files changed, 54 insertions(+), 1 deletion(-)
     create mode 100644 ansible-apache/install_apache_options_playbook.yaml
     create mode 100644 ansible-apache/install_apache_playbook.yaml
     create mode 100644 ansible-apache/test_apache_playbook.yaml
    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$
    
  4. Push all the changes you made in the local repository back to the GitHub repository to complete the lab. Remember to use your Personal Access Token when asked for your GitHub password.

    Tip

    If you’ve configured your VM to use SSH to connect to GitHub instead of HTTPS, you will not be asked for a username and password, although you may be asked for a passphrase for your SSH key, if you configured one.

    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$ git push origin main
    Username for 'https://github.com': username
    Password for 'https://username@github.com': Personal Access Token
    Enumerating objects: 26, done.
    Counting objects: 100% (23/23), done.
    Delta compression using up to 2 threads
    Compressing objects: 100% (18/18), done.
    Writing objects: 100% (19/19), 4.91 KiB | 4.92 MiB/s, done.
    Total 19 (delta 3), reused 0 (delta 0), pack-reused 0 (from 0)
    remote: Resolving deltas: 100% (3/3), completed with 1 local object.
    To github.com:Ontario-Tech-NITS/lab-6-infrastructure-automation-josh-test-student.git
       aa2d83e..3e465ca  main -> main
    devasc@labvm:~/labs/devnet-src/ansible/ansible-apache$
    
  5. In your browser, return to the repository on github.com and verify all your changes are present, along with the corresponding commit messages. Wait a minute or so for the autograder tests to complete and ensure that it says passing in green.

    Screenshot of successful autograder tests